Skip to content

feat(plugin): emit connector.plugin_not_found ConduitError code#2528

Merged
devarismeroxa merged 2 commits into
mainfrom
feat/conduiterr-plugin-not-found
Jul 5, 2026
Merged

feat(plugin): emit connector.plugin_not_found ConduitError code#2528
devarismeroxa merged 2 commits into
mainfrom
feat/conduiterr-plugin-not-found

Conversation

@devarismeroxa

Copy link
Copy Markdown
Contributor

Step 3 of the structured-error rollout — the first real error source migrated to a ConduitError code, exercising the API boundary from #2527.

When the builtin connector registry can't find a plugin (unknown name, or 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. The plugin.ErrPluginNotFound sentinel stays in the chain, so existing errors.Is checks are unaffected (existing tests pass 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 — the first genuine machine-actionable code an API/MCP/UI consumer sees.

Test augmented to assert both the sentinel Is-check and the new code + suggestion. Tier 2 (additive; backward-compatible). Advances #2451.

🤖 Generated with Claude Code

devarismeroxa and others added 2 commits July 5, 2026 14:35
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>
@devarismeroxa devarismeroxa requested a review from a team as a code owner July 5, 2026 21:56
@devarismeroxa devarismeroxa merged commit 72c993b into main Jul 5, 2026
5 checks passed
@devarismeroxa devarismeroxa deleted the feat/conduiterr-plugin-not-found branch July 5, 2026 22:02
devarismeroxa added a commit that referenced this pull request Jul 5, 2026
…2530)

Step 4 of the structured-error rollout: two more error sources now emit
ConduitError codes instead of bare sentinels, following the pattern from
connector.plugin_not_found (#2528).

- pipeline.ErrInstanceNotFound, raised in pipeline.Service.Get (the sole
  choke point — Update/Delete/AddConnector/etc. all call Get internally),
  now wraps with a new code pipeline.instance_not_found (codes.NotFound)
  and a suggestion to run `conduit pipelines list`.
- connector.ErrInstanceNotFound, raised in connector.Service.Get (same
  choke-point property), wraps with connector.instance_not_found
  (codes.NotFound) and a suggestion to run `conduit connectors list`.

Both sentinels remain in the error chain via conduiterr.Wrap, so existing
errors.Is(err, ErrInstanceNotFound) checks throughout pkg/provisioning,
pkg/orchestrator, and pkg/http/api/status are unaffected — verified by
running those suites plus pkg/lifecycle(-poc). Tests augment
TestService_GetInstanceNotFound in both packages to assert the sentinel
Is-check AND the new code + non-empty Suggestion via conduiterr.Get.

processor.ErrInstanceNotFound is a separate, un-migrated error source
(pkg/processor/service.go) — left out of scope for this step to keep the
blast radius tight; it's a natural next candidate.

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

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
devarismeroxa added a commit that referenced this pull request Jul 6, 2026
…gin registries) (#2532)

Finishes the not-found migrations begun in the connector-plugin (#2528) and
pipeline/connector-instance (#2530) PRs:

- processor.instance_not_found (CodeProcessorNotFound, pkg/processor/codes.go):
  Service.Get now wraps ErrInstanceNotFound with the code + a suggestion — the
  single choke point every processor method routes through.
- processor.plugin_not_found (CodeProcessorPluginNotFound): the builtin and
  standalone processor registries now emit the code when a plugin/version is
  missing, mirroring the connector builtin registry from #2528.
- connector.plugin_not_found: the standalone connector registry now emits the
  code too, completing the connector plugin-not-found set (builtin was #2528).

All sites keep the original sentinel in the chain via conduiterr.Wrap
(errors.Is(err, ErrInstanceNotFound) / plugin.ErrPluginNotFound unaffected;
invariant noted at each site). Purely additive.

Test: TestService_Get_Fail asserts both the sentinel Is-check and the new code +
suggestion. Existing registry/service suites pass unchanged.

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