feat: hint at extension dependency when plan fails with missing object errors (#436)#468
Conversation
…t errors (#436) When the desired state depends on a PostgreSQL extension (e.g. btree_gist, citext, pgvector) that is absent from the plan database, applying the schema fails with an opaque error like: ERROR: data type uuid has no default operator class for access method "gist" pgschema intentionally does not manage extension lifecycle (database-level object), so detect the common SQLSTATEs for this failure mode — 42704 undefined_object and 42883 undefined_function — and append a hint pointing to the external plan database (https://www.pgschema.com/cli/plan-db): - embedded path: suggest --plan-host, since embedded postgres cannot provide extensions at all - external path: suggest installing the extension in the plan database Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile SummaryThis PR adds extension-dependency hints when desired-state planning fails on missing PostgreSQL objects. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Reviews (1): Last reviewed commit: "feat: hint at extension dependency when ..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
This PR improves the usability of plan failures caused by missing PostgreSQL extension-provided objects by detecting common “missing object” SQLSTATEs during desired-state apply and appending a provider-specific hint explaining how to resolve the issue (embedded vs external plan DB).
Changes:
- Added
hintExtensionDependencyto append an actionable hint for SQLSTATE42704(undefined_object) and42883(undefined_function) errors. - Wired the hint into the desired-state apply error path for both embedded and external plan database providers with tailored guidance.
- Added unit tests covering the hinting behavior, including interaction with existing
enhanceApplyErrorwrapping and pass-through for other error types.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| internal/postgres/desired_state.go | Adds helper to detect missing-object SQLSTATEs and append an extension-dependency hint while preserving error unwrapping. |
| internal/postgres/embedded.go | Appends an embedded-specific hint explaining embedded plan DBs can’t provide extensions and suggesting --plan-host. |
| internal/postgres/external.go | Appends an external-specific hint advising to install the missing extension in the plan database (CREATE EXTENSION). |
| internal/postgres/desired_state_test.go | Adds tests for hinting behavior, wrapping compatibility, and pass-through cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Follow-up to #436 (and the discussion in #121 / #437): pgschema intentionally does not manage extension lifecycle, but the error users hit when their schema depends on an extension is opaque:
This PR detects the common SQLSTATEs for this failure mode during desired-state apply —
42704undefined_object (missing type / operator class) and42883undefined_function (missing function / operator) — and appends a hint pointing at the supported solution:--plan-host), since the embedded postgres binaries cannot provide extensions at allCREATE EXTENSION)Both hints link to https://www.pgschema.com/cli/plan-db. Errors with other SQLSTATEs (and non-PostgreSQL errors) pass through unchanged.
Example output for the repro in #436 (EXCLUDE USING gist on uuid, requires
btree_gist):Changes
internal/postgres/desired_state.go: newhintExtensionDependencyhelperinternal/postgres/embedded.go,internal/postgres/external.go: wire the hint into the desired-state apply error path with provider-specific wordinginternal/postgres/desired_state_test.go: unit tests covering both SQLSTATEs, composition with the existing error-location snippet, and pass-through behaviorTesting
go test ./internal/postgrespasses🤖 Generated with Claude Code