Changelog - 2026-10-14
An error hands out its filled text
EnhancementIn one line. error.toFilledText() gives the sentence a person reads; error.message stays the template.
typescript
const error = getError({
message: { text: 'Only %{available} left of %{sku}.', code: 'stock.unavailable' },
messageArgs: { available: 2, sku: 'TRA-01' },
statusCode: 409,
});
error.toFilledText(); // 'Only 2 left of TRA-01.'
error.message; // 'Only %{available} left of %{sku}.'What changed
The error response already filled its message (2026-10-11). A reader outside the response did not get that: a BullMQ job stores job.failedReason = error.message, so its dashboard showed %{available}.
toFilledText()onApplicationErrorfills each%{key}fromnormalized.args. A key with no arg stays as written.MessageTemplate.render({ text, args })is the fill itself, exported from@venizia/ignis-inversionand@venizia/ignis-helpers. It also returns the keys it found no arg for. The error middleware uses it, so the response andtoFilledText()fill the same way.messagedoes not change. A filledmessagewould print every arg value in each log line and error tracker, outside theargsmap the log redacts by key. Fill where you choose to store the text.
Who is affected
- A queue, tracker or log that stores
error.message. CalltoFilledText()where you hand the error over - see Store the filled text. - A client that casts a response error to
ApplicationError. The cast object has notoFilledText(); calling it throws at run time. UsefromError({ error }).toFilledText(), or the responsemessage, which the server already fills. - An object literal typed
ApplicationError- a test fixture, a mock - no longer compiles, because it lacks the method. Build it withgetError(...). - Everyone else. No change.
Files: packages/inversion/src/modules/error/message-template.ts, packages/inversion/src/modules/error/app-error.ts, packages/kernel/src/base/middlewares/app-error/app-error.middleware.ts