Typed bookkeeping Error instances passed to getErrorMessage() matched the
bare-envelope branch (any object with string code + message) and returned
their raw English message verbatim, so the categorize and match-invoice
routes surfaced strings like DB check-constraint violations directly in the
user's toast (issue #337).
- get-error-message.ts: when the bare-envelope shape is an Error instance,
normalize it into the structured envelope ({ error: { code, message,
account_numbers, details } }) so the existing per-code Swedish branches
own the translation; plain forwarded envelopes keep the passthrough.
- get-error-message.ts: structured-path final fallback now prefers the
registry's message_sv for known codes whose message is not Swedish, so
typed codes without a dynamic branch (e.g. CANNOT_REVERSE_STORNO) cannot
surface English either.
- categorize + match-invoice routes: always map the caught error through
getErrorMessage (the raw error is already logged); untyped errors fall to
the Swedish context fallback instead of leaking err.message.
- Tests: new instance-translation suite in lib/errors, typed-error case in
the categorize route suite, and deliberate updates of the two tests that
pinned raw 'Period locked' passthrough.
Fixes#337
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>