Papers

Error Envelope Migration — v1 → v2

Sunset policy

v1 is not scheduled for removal. Minimum runway after v2 GA is one minor release; actual sunset will be announced explicitly in this document. TUI and curl-based workflows depend on the v1 shape and need a coordinated migration. Until the announcement lands, treat v1 as permanent.

Rollout when scheduled:

  1. v2 becomes default; v1 works via Accept-Version: 1.
  2. v1 emits Deprecation response header (RFC 8594 / RFC 9745) with a sunset date.
  3. v1 removed; requests without Accept-Version get v2.

Each step is gated on the public Studio + TUI clients confirming they have moved.

Why v2

Phase 3 introduced a structured error envelope so SDK clients, pipeline tools, and Studio can render per-field validation diagnostics without parsing free-form strings.

Wire shapes

Select with Accept-Version: 2 header. Non-validation errors (not_found, unauthorized, precondition_failed, etc.) are unchanged in v2 — negotiation only reshapes validation_failed.

Headerabsent or Accept-Version: 1Accept-Version: 2
Validation keyerror.details%{field => [str]}error.errors%{path => [violation]}
Path formatflat field nameJSON Pointer (/contributors/0/role)
Per-violationbare string{severity, code, message, rule}
Bucketserrors onlyerrors, warnings, infos

Implementation pointers

  • Module: BarkparkWeb.ErrorEnvelope (serialize_v1/1, serialize_v2/1)
  • Plug: BarkparkWeb.Plugs.ErrorEnvelopeNegotiation — wired into :api, :scoped_api, :api_unlimited, :api_preview, :media_mutate, :media_processing_callback
  • Today only MutateController reshapes for validation_failed v2; other controllers pick up the assign automatically when they need it
  • Code registry: Barkpark.Content.ErrorCodes — compile-time map atom → %{message_template, default_severity, since_version}; new codes are additive