Skip to content

feat(cerrors): ConduitError foundation (type, registry, proto mapping)#2524

Merged
devarismeroxa merged 2 commits into
mainfrom
feat/conduit-error-foundation
Jul 5, 2026
Merged

feat(cerrors): ConduitError foundation (type, registry, proto mapping)#2524
devarismeroxa merged 2 commits into
mainfrom
feat/conduit-error-foundation

Conversation

@devarismeroxa

Copy link
Copy Markdown
Contributor

First, no-behavior-change step of the v0.16 structured-error work (design: docs/design-documents/20260705-conduit-error-and-structured-output.md, PR #2523). Adds the conduiterr package; touches no existing error site.

What's here

  • ConduitError {Code, Message, ConfigPath, Suggestion, Fix, DocsURL} — composes with cerrors (wraps a cause, preserves stack traces; errors.As/Is work).
  • New/Wrap are the only constructors. New guarantees a stack frame even for a leaf error (a bare &ConduitError{} literal carries none — it's not an xerrors value; a test enforces this). Wrap honors the no-nested-code invariant — it passes an inner ConduitError's code through rather than shadowing it.
  • Code registry with an explicit gRPC category per code (not inferred from the reason string). Codes() feeds docs/llms.txt/UI.
  • ToStatus/FromStatus map to/from google.rpc.Status with an additive google.rpc.ErrorInfo detail (the compat path verified through grpc-gateway in the design review). Top-level code/message unchanged.

Tests

  • Round-trip test pins the Go↔wire encodings so they can't drift.
  • A fuzz test found and fixed a real bug: a stray invalid-UTF-8 byte in any field made the proto detail fail to marshal, silently dropping the entire structured error. ToStatus now coerces wire strings to valid UTF-8. Fuzz then ran 2.4M execs clean.
  • -race green, lint clean, linux/386 builds.

Tier 2 (new foundation package, no data-path change, no existing behavior touched).

🤖 Generated with Claude Code

…ping)

First, no-behavior-change step of the v0.16 structured-error work: the Go
representation of Conduit's uniform, machine-actionable error, plus its wire
mapping. No existing error site is touched.

- ConduitError{Code, Message, ConfigPath, Suggestion, Fix, DocsURL} composes with
  cerrors (wraps a cause, preserves stack traces; errors.As/Is work).
- New/Wrap are the only constructors. New guarantees a stack frame even for a leaf
  error (a bare *ConduitError literal carries none — it is not an xerrors value;
  test enforces this). Wrap honors the no-nested-code invariant: it passes an
  inner ConduitError's code through unchanged rather than shadowing it.
- Code registry with an EXPLICIT gRPC category per code (not inferred from the
  reason string); Codes() feeds docs/llms.txt/UI.
- ToStatus/FromStatus map to/from google.rpc.Status with an additive
  google.rpc.ErrorInfo detail (verified preserved through grpc-gateway). Top-level
  code/message unchanged — purely additive.
- Round-trip test keeps the Go and wire encodings from drifting; a fuzz test
  found and fixed a real bug: a stray invalid-UTF-8 byte in any field made the
  proto detail fail to marshal, silently dropping the whole structured error.
  ToStatus now coerces wire strings to valid UTF-8.

Design: docs/design-documents/20260705-conduit-error-and-structured-output.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@devarismeroxa devarismeroxa requested a review from a team as a code owner July 5, 2026 19:07
…onest docs

Review fixes for the ConduitError foundation (#2524):
- Sanitize Code.Reason on the wire like every other field (a stray byte would
  otherwise fail the detail marshal and drop the whole structured error).
- Export Register with a documented init-only contract so boundary packages can
  register their own codes (the rollout's next step needs this).
- Correct New/Wrap docstrings: the guaranteed stack frame points into the
  constructor, not the caller (cerrors.New uses Caller(1)); guide toward Wrap with
  a cerrors cause for accurate attribution. Real skip-aware fix tracked as
  follow-up.
- Document Wrap's message-replace behavior and that its code arg is ignored when
  an inner ConduitError is present; comment the local-registry-authoritative
  GRPCCode decision; godoc on Code/Message/Error/Unwrap.
- Strengthen the fuzz: vary the Code and add an idempotent relay round-trip (the
  check that catches a field silently failing to marshal); add an invalid-UTF-8
  seed.

Follow-ups (caller-accurate frames, raw-literal guard, code-override hatch): filed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant