feat(config): emit ConduitError codes + configPath for pipeline validation#2529
Merged
Conversation
Step 2 of the structured-error rollout: the ConduitError foundation now reaches the API. When an error returned to a gRPC/HTTP handler carries a *ConduitError (anywhere in its chain), status.go emits its gRPC category plus an additive google.rpc.ErrorInfo detail carrying the stable reason, configPath, suggestion, and fix — so an API/MCP/UI consumer gets a machine-actionable error. This is a single integration point (conduitErrorStatus, checked at the top of PipelineError/ConnectorError/ProcessorError/PluginError). It is purely additive: any error that is NOT a ConduitError falls through to the existing sentinel->code mapping, byte-for-byte unchanged (existing tests still pass). Boundaries get migrated to emit ConduitError codes incrementally from here. Tests: a wrapped ConduitError yields the right code + ErrorInfo detail (reason, configPath, suggestion); a sentinel error maps exactly as before. Design: docs/design-documents/20260705-conduit-error-and-structured-output.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 3 of the structured-error rollout — the first real error source migrated to a ConduitError code, exercising the API boundary wired in the previous step. When the builtin connector registry can't find a plugin (unknown name, or a known name with no matching version), it now returns a ConduitError with code `connector.plugin_not_found` and a suggested fix, instead of a bare sentinel / generic wrapped error. The `plugin.ErrPluginNotFound` sentinel remains in the chain, so existing `errors.Is` checks are unaffected (invariant noted at the site; existing tests unchanged). End to end: registry -> ConduitError(code, suggestion) -> orchestrator -> API (status.ConnectorError/PluginError) -> ToStatus -> a google.rpc.ErrorInfo detail carrying reason=connector.plugin_not_found + the suggestion, on the wire. Test augments TestRegistry_NewDispenser_PluginNotFound to assert both the sentinel Is-check AND the new code + suggestion. Design: docs/design-documents/20260705-conduit-error-and-structured-output.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation Structured-error rollout: pipeline-config validation now attaches a machine-actionable code and a JSON-pointer configPath to the offending field for every validation error — so an API/MCP/UI consumer gets exactly what is wrong and where (e.g. code=config.field_required, configPath=/connectors/0/processors/0/id), not just a prose string. This delivers the "failing config path" half of the machine-actionable-errors promise. - codes.go registers config.field_required/field_invalid/field_too_long/ id_duplicate and a fieldError helper. - Validate/validateConnectors/validateProcessors build the JSON-pointer per field (validateProcessors takes a pathPrefix so nested connector processors get /connectors/i/processors/j/...). - The original sentinels (ErrMandatoryField, ErrInvalidField, ErrDuplicateID, pipeline/connector over-limit errors) stay in the chain — existing errors.Is checks and tests are unaffected. Codes flow through the API boundary wired earlier: ConduitError -> ToStatus -> google.rpc.ErrorInfo with reason + configPath, on the wire. Design: docs/design-documents/20260705-conduit-error-and-structured-output.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Structured-error rollout — the
configPathstep. Pipeline-config validation now attaches a machine-actionable code and a JSON-pointer to the offending field for every validation error.Before:
"plugin" is mandatory. After:code=config.field_required,configPath=/connectors/0/processors/0/id— an agent or UI knows exactly what to fix and where. This delivers the "failing config path" half of the machine-actionable-errors promise.What changed
codes.go: registersconfig.field_required/field_invalid/field_too_long/id_duplicate+ afieldErrorhelper.validate.go: each check builds its JSON-pointer;validateProcessorstakes apathPrefixso nested connector processors get/connectors/i/processors/j/....errors.Ischecks and tests are untouched (they pass unchanged).Codes flow through the boundary wired in #2527:
ConduitError → ToStatus → google.rpc.ErrorInfowith reason + configPath, on the wire.Tests
TestValidate_ConfigPathAndCodeasserts the code + exact path for pipeline/connector/nested-processor fields; the full provisioning suite passes unchanged.Tier 2 (additive, backward-compatible). Advances #2451 and the v0.16 structured-error work.
🤖 Generated with Claude Code