# CNT-1 — Error messages state what happened and what to do next; no raw error codes as the primary message

L1 · hybrid · Content & naming

**Fails when:** "Something went wrong" with no next step · stack traces or codes shown to users

## Requirement

Every error message answers, in order: what happened, what it means for the user,
and what to do next. Calm and helpful in tone. Raw error codes never appear as the
primary message (they may appear as secondary detail for support).

## Rationale

Kind at Surface: gentle error states with clear next steps, never technical error
codes or dismissive generic errors. An error moment is where a tired user decides
whether this tool is on their side.

## Passes when

- "We could not save your notes — the connection dropped. Your draft is kept on this
  device; try again when you're back online."
- A failed action keeps the user's entered data and says so.
- Where a code aids support, it is secondary: "…contact support and quote ref 4031."

## Fails when

- "Error 500" / "Something went wrong" as the whole message.
- The message blames the user ("You entered invalid data") instead of stating the
  problem ("We don't recognise this date format — use DD/MM/YYYY").
- The message states what happened but not what to do next.
- An error discards the user's input silently.

## How to verify

Deterministic half — `checks/content-lint.py`: find error-state strings, flag
raw codes appearing as primary copy. The lint half flags a raw code only where it can
tell a code from a name: a bare string literal, or a Markdown prose line. It does not
flag one in rendered text, a prop value, or a template segment, where an all-caps
token is as likely a wordmark, a badge, or an acronym. It also never reads a compared
value (`tag === "INPUT"`) as copy. Judgment half — the evaluator quotes each error
message and grades it against the three questions, using the tone-by-context table in
the `content` skill (error tone: calm, helpful).
