refactor(server): sweep three inline errorMessage ternaries onto the shared helper (#tech-debt) - #1079
Merged
Merged
Conversation
…shared helper (#tech-debt) `errorMessage` in apps/server/src/shared/lib/error-message.ts is literally `error instanceof Error ? error.message : String(error)`. Three sites had re-inlined that exact ternary since the last sweep (#914/#926): - apps/server/src/agents/pin-write.ts:52 - apps/server/src/shared/plugin-status.ts:124 - apps/server/src/shared/mcp/whiteboard-tools.ts:338 Textually identity-preserving — no behavior change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three sites had re-inlined the exact body of
errorMessage(apps/server/src/shared/lib/error-message.ts, which iserror instanceof Error ? error.message : String(error)). They now import it:apps/server/src/agents/pin-write.tsnew AgentError(error instanceof Error ? error.message : String(error), 400)apps/server/src/shared/plugin-status.ts{ error: err instanceof Error ? err.message : String(err) }apps/server/src/shared/mcp/whiteboard-tools.ts`${error instanceof Error ? error.message : String(error)} — call whiteboard_howto …`+6/-6 across 3 files. The substitution is textual identity — same expression, same result for every input — so there is no behavior change.
Why it's tech debt
Recurring, tracked regression.
errorMessagewas fully consolidated across the server in #914 and across web in #926 (2026-08-09/10). The Brain's pattern entry predicted a re-sweep every 6–12 months; the 2026-09-05 audit found these three had already crept back within four weeks, and the sharpest signal from #914 was that the helper is not hard to find — it is muscle memory when writing a newtry/catch.What the three included sites have in common — precisely
All three are
catchblocks that convert an unknown thrown value to a string using the bareString(x)fallback, with no domain-specific default. Inwhiteboard-tools.tsthe— call whiteboard_howto …suffix sits outside the ternary, so it survives interpolation unchanged.Deliberate exclusions (do not re-flag)
grep -rn 'instanceof Error' apps/server/src apps/web/srcfinds 52 sites. The 48 not touched here fall into two groups, anderrorMessagecannot express either:release-info.ts: "migration evaluation failed",agents/archive.ts: "Archive failed",http-helpers.ts: "Unknown error.",routes/personas.ts: "Invalid model.", and every web site (use-notification-settings.ts: "Failed to save.",branch-select.tsx: "Couldn't load branches.", …). Swapping inerrorMessagewould replace a curated user-facing message withString(undefined)-class output. Behavior change, not a sweep.config.ts:error instanceof Error && error.message.startsWith("Refusing to use"),media-lightbox.tsx,use-chat-surface-enabled.ts,use-terminal.ts,service-resources.ts. These useinstanceofto branch, not to stringify.Also excluded:
bin/embed-assisted-update.ts:77,88carry the same ternary, butbin/is a standalone script compiled undertsconfig.scripts.jsonand does not import fromapps/server/src; pulling in a server module for two lines is a bigger blast radius than the debt.Liveness check (dead-site rule)
Each of the three enclosing functions was confirmed reachable from within its declaring file before the edit:
validateStoredPinhas 4 call sites inpin-write.ts(165, 181, 234, 252);runStephas 5 inplugin-status.ts(209, 225, 291, 355, 512); thewhiteboard_updatehandler is registered underif (allowed.has("whiteboard_update") && context.updateWhiteboard)at line 284.Validation
pnpm run check— clean (server, web, site).pnpm run test— 186+128+9 files, 5227 tests, 0 failures (Postgres viarepo_dev_up,TEST_DATABASE_URL/DATABASE_URLexported).pnpm run test:e2e— 198 passed, 12 skipped.apps/web/files changed, sofinalize:webis not applicable.Probe results, reported honestly. I probed each swept site by replacing the call with a constant and re-running its colocated suite:
whiteboard-tools.ts→mcp-whiteboard-tools.test.tsfails (1 of 3). Covered.pin-write.ts→pin-write.test.tsstayed green (36/36). Its tests exercise merge/label/id rejection paths; nothing drivesvalidatePinValueinto throwing throughvalidateStoredPin, so the wrapper's message text is unasserted.plugin-status.ts→plugin-status.test.tsstayed green (20/20). Deliberate:runStep's raw text never reaches an assertion because the caller replaces it with a curated message ("Failed to refresh the dispatch marketplace.","Failed to update the plugin."— lines 317, 335).I did not add tests to close those gaps: the substitution is textually identical to the code it replaces, so a new test would assert the helper's behavior, not this diff's. Flagging the two coverage gaps as an observation rather than manufacturing coverage for a no-op change.
Next run
Queued: the complexity hotspot
apps/web/src/components/app/chat/chat-entries.tsx(1180 lines, now the largest web component in the repo, landed across #1042–#1056 and never audited).🤖 Generated with Claude Code