Skip to content

feat: emit pipeline/connector instance_not_found ConduitError codes#2530

Merged
devarismeroxa merged 1 commit into
mainfrom
feat/conduiterr-instance-not-found
Jul 5, 2026
Merged

feat: emit pipeline/connector instance_not_found ConduitError codes#2530
devarismeroxa merged 1 commit into
mainfrom
feat/conduiterr-instance-not-found

Conversation

@devarismeroxa

Copy link
Copy Markdown
Contributor

Summary

Step 4 of the structured-error rollout (follows #2528, #2527, #2524). Migrates two more error sources to emit ConduitError codes, exercising the API boundary wired in #2527, following the exact pattern used for connector.plugin_not_found.

  • pipeline.ErrInstanceNotFound — raised in pipeline.Service.Get, the sole construction site (every other method — Update, Delete, AddConnector, AddProcessor, etc. — calls Get internally, so this single choke point covers all not-found paths). Now wraps with a new code pipeline.instance_not_found (codes.NotFound, registered in new pkg/pipeline/codes.go) and a suggestion to run conduit pipelines list.
  • connector.ErrInstanceNotFound — same treatment in connector.Service.Get (same choke-point property). New code connector.instance_not_found (codes.NotFound, registered in new pkg/connector/codes.go), suggestion to run conduit connectors list.

Both sentinels remain in the error chain via conduiterr.Wrap(code, msg, sentinel), so this is additive and backward-compatible: any error that is not one of these two sentinels is unaffected, and existing errors.Is(err, ErrInstanceNotFound) checks across pkg/provisioning, pkg/orchestrator, and pkg/http/api/status continue to hold unchanged — no behavior change for consumers that only check errors.Is. Consumers reading the error through conduiterr.Get now additionally get a stable machine-actionable code + suggestion.

Deliberately out of scope: processor.ErrInstanceNotFound (pkg/processor/service.go) is a separate, un-migrated error source with the same shape — left for a follow-up PR to keep this change's blast radius tight (single choke point in each of two packages, not a third).

Self-review (adversarial pass, per CLAUDE.md)

  • conduiterr.Wrap's "inner ConduitError code wins" branch doesn't fire here — both sentinels are plain cerrors.New(...) values, not existing *ConduitErrors, so the new code is always the one that lands. Confirmed via Wrap's cerrors.As(cause, &inner) check.
  • No duplicate-registration panic risk: grepped the registry for instance_not_found — each reason (pipeline.instance_not_found, connector.instance_not_found) is registered exactly once.
  • No test or call site asserts on the exact Get-produced message text (old: "pipeline instance not found (ID: %s)", new: "pipeline %q not found") — everywhere else uses errors.Is, not string comparison, so the wording change is safe.
  • pkg/http/api/status/status_test.go's existing TestPipelineError/TestConnectorError/TestNonConduitErrorUnchanged cases pass the bare sentinel directly into PipelineError/ConnectorError (not through Service.Get), so they're unaffected by this change and remain green as regression coverage for the "non-ConduitError" fallback path.

Test plan

  • go build ./... clean
  • go test ./pkg/pipeline/... ./pkg/connector/... ./pkg/http/api/status/... -count=1 — green
  • go test ./pkg/orchestrator/... ./pkg/provisioning/... ./pkg/lifecycle/... ./pkg/lifecycle-poc/... -count=1 — green (confirms no downstream errors.Is regressions)
  • golangci-lint run ./pkg/pipeline/... ./pkg/connector/... (v2.12.2) — 0 issues
  • TestService_GetInstanceNotFound augmented in both pkg/pipeline and pkg/connector to assert the sentinel errors.Is check AND conduiterr.Get(err) returns the new code with a non-empty Suggestion, mirroring the connector.plugin_not_found test augmentation

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

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tapg9dLWXKMZJoL65R24vd

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 devarismeroxa requested a review from a team as a code owner July 5, 2026 23:49
@devarismeroxa devarismeroxa merged commit 38dfc4c into main Jul 5, 2026
5 checks passed
@devarismeroxa devarismeroxa deleted the feat/conduiterr-instance-not-found branch July 5, 2026 23:55
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