Skip to content

Replace inline errorMessage duplicates in the server - #914

Merged
selfcontained merged 1 commit into
mainfrom
tech-debt/error-message-server-sweep
Aug 9, 2026
Merged

Replace inline errorMessage duplicates in the server#914
selfcontained merged 1 commit into
mainfrom
tech-debt/error-message-server-sweep

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

What

apps/server/src/shared/lib/error-message.ts is the canonical helper for turning an unknown catch value into a string:

exportfunctionerrorMessage(error: unknown): string{returnerrorinstanceofError ? error.message : String(error);}

18 sites across 11 server modules had re-inlined that exact expression instead of importing it. This replaces them with errorMessage(...):

FileSites
release-checks.ts4
server/release-runtime.ts3
jobs/service.ts2
update-migrations.ts2
agents/manager.ts (already imported the helper)1
assisted-update.ts1
observability/subsystem-tracker.ts1
personas/authoring.ts1
release-info.ts1
routes/release.ts1
shared/mcp/tool-error.ts (inner branch of a longer chain)1

Why this is tech debt

This is a regression of the consolidation landed in #608. The tech-debt Brain has a standing pattern note that this exact helper "does not stay fixed on its own" — every new try/catch is an opportunity to retype the ternary instead of adding the import. The duplication is harmless in isolation but it is the reason nobody can change the helper's behavior in one place.

Scope / what was deliberately left alone

Only byte-equivalent occurrences were replaced. A repo-wide grep for instanceof Error found 19 other sites that look similar but are not the same function, and none of them were touched:

  • Different fallback string — "Unknown error" (notifications/slack.ts, routes/release.ts:465,486, release-info.ts:243), "Unknown error." (server/http-helpers.ts), "Archive failed" (agents/archive.ts), "Invalid model." (routes/personas.ts), "invalid JSON metadata" (release-metadata.ts), "migration evaluation failed" (release-info.ts:211), "Failed to substitute variables." (routes/agents/terminal-routes.ts), "Database probe failed" (observability/service-resources.ts), "Prompt delivery failed." (routes/browser-extension.ts, which also truncates via .slice(0, 2_000)).
  • Different result type — release-tarball-cache.ts:210 and server/mcp-handlers.ts:577 rethrow an Error, not a string.
  • Not a to-string at all — config.ts:165 (a startsWith guard), db/seed/run.ts:41 (fallback is the raw value, not String(...)).

Web-side duplicates (apps/web/src/components/app/jobs-helpers.tsx:73 reimplements the helper, components/ui/markdown.tsx:211 inlines it) are not in this PR — that half needs a re-export decision through @/lib/... and stays on the tech-debt backlog for a future run.

Behavior

None. errorMessage() is byte-identical to what each replaced site inlined.

Validation

  • pnpm run check — green
  • pnpm run test — green (2503 server + 705 web + 60, 0 failures)
  • pnpm run test:e2e — 178 passed, 12 skipped
  • finalize:web not run: no apps/web/ files changed

Queued for the next run

Backlog top item after this: the web half of this same sweep, then the formatDate name-collision cleanup across activity-chart-utils.ts / release-utils.ts / jobs-helpers.ts.

🤖 Generated with Claude Code

`apps/server/src/shared/lib/error-message.ts` is the canonical helper for
turning an unknown catch value into a string, but 18 sites across 11
server modules had re-inlined `error instanceof Error ? error.message :
String(error)` instead of importing it. This is a regression of the
consolidation done in #608 — the pattern creeps back in every time a new
try/catch is written.
Replaced only byte-equivalent occurrences. Sites with a different
fallback ("Unknown error", "Archive failed", "Invalid model.", the
`.slice(0, 2_000)` truncation in browser-extension.ts) or a different
result type (the variants that rethrow an `Error` rather than produce a
string) are intentionally left alone — they are not the same function.
No behavior change; `errorMessage()` is byte-identical to what each site
inlined.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@selfcontained
selfcontained merged commit 23dfa05 into mainAug 9, 2026
1 check passed
@selfcontained
selfcontained deleted the tech-debt/error-message-server-sweep branch August 9, 2026 09:14
selfcontained added a commit that referenced this pull request Aug 10, 2026
Completes the errorMessage sweep started server-side in #914. apps/web
carried a byte-identical reimplementation in jobs-helpers.tsx plus one
inline copy in markdown.tsx; both now route through the canonical
apps/server/src/shared/lib/error-message.ts.
Web imports a VALUE here, so it follows the #844/#849 shape: a new
dependency-free re-export module at apps/web/src/lib/errors.ts keeps call
sites on "@/lib/..." instead of reaching across the boundary directly.
Test coverage for the helper already exists in
apps/server/test/error-message.test.ts and is a strict superset of the
jobs-helpers.test.tsx block, which is dropped.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@selfcontained