A change to a common list is refused — and turned into a way forward
The detail page never offers edit controls on a common list (editable: false), so this is
reached through a deep link, a stale page, or a role revoked mid-session. Here: Sam opened the French translation editor of
Priority from a bookmark and pressed Save.
Kept exactly as typed — never cleared by the refusal. Copy it before you leave.
403 vs 409 — the difference is whether you may fork
The service decides, in this order (design record D7): unreadable → 404;
readable but not writable → 409 fork_required if you hold SelectionListCatalog:create,
else 403. The UI branches on code + reason only — never on its own
guess of your role.
409 CONFLICT · reason fork_required
403 FORBIDDEN — no create (e.g. a viewer)
403 FORBIDDEN — access management on a common list
404 NOT_FOUND — not readable at all
Fail-closed rules
- A
409withoutreason(key taken, last owner, …) is the ordinary conflict message from the 4.0.0 frames — the fork banner renders only forreason: fork_required. - The Fork CTA uses
source_list_idfrom the error body, not the id in the page URL — the 409 names the list the service refused. fork_urlis relative (/v1/…) and is resolved against the same-origin API base. A body carrying an absolute URL is ignored and the client's ownforkList(sourceListId)is used.- The same ForkRequiredBanner renders wherever a mutation can be refused: the value editor, the reorder save, the list settings, the translation workbench and auto-fill. It sits next to the control that was refused, not in a global toast.
- The refusal never auto-forks. Forking creates a list in the organization and costs quota — it is always an explicit choice in the next dialog.
- Flag OFF: the service answers 4.0.0 behaviour and no common list is reachable, so this banner cannot appear; the UI does not render it even if a stray
reasonarrives.
Test hooks: [data-frame='04-fork-required'] · [data-panel='mutation-attempt'] · [data-unsaved='true'] · [data-error='CONFLICT'][data-reason='fork_required'] · [data-action='fork-to-edit'] · [data-fork-url] · [data-action='back-to-list'] · [data-error='FORBIDDEN'][data-case='common-no-create'] · [data-error='FORBIDDEN'][data-case='common-access'] · [data-error='NOT_FOUND']
Contract: any per-list mutation (list update/delete/archive, item create/update/reorder/delete/archive, translation upsert/delete/autofill) →
409 Error{code: CONFLICT, reason: fork_required, source_list_id, fork_url} or 403 FORBIDDEN.
Tokens only — no raw hex, spacing or type outside tokens.css / frame.css.