Troubleshooting
Checksum mismatch on an applied migration
Section titled “Checksum mismatch on an applied migration”status and migrate compare each applied migration’s recorded checksum with
the file on disk. A mismatch means the file changed after it was applied —
usually someone edited a migration instead of adding a new one. Restore the
original SQL and write a follow-up migration for the change.
Checksums are computed on comment-stripped SQL, so adding or editing comments
(including shki: directives) does not invalidate one.
A CREATE INDEX CONCURRENTLY migration failed
Section titled “A CREATE INDEX CONCURRENTLY migration failed”A failed concurrent index build leaves an INVALID index behind, and a re-run
guarded by IF NOT EXISTS would silently keep it. Check pg_index.indisvalid,
DROP INDEX the invalid one, then re-run the migration. See
running outside a transaction.
generate fails asking about CONCURRENTLY
Section titled “generate fails asking about CONCURRENTLY”When the Declarative Schema declares CREATE INDEX CONCURRENTLY,
shki generate writes a second,
no-transaction migration for the index builds — and asks for confirmation
first, since the output changes shape. Declining, or running without a terminal
(CI, scripts), fails the whole generation and writes nothing. Run generate
interactively and confirm, or remove CONCURRENTLY from the schema to get a
single plain migration.
Shadow Database refused
Section titled “Shadow Database refused”Two guards protect against pointing shki at a database it may reset:
-
shadow_database_urlmust not equaldatabase_url. -
An external Shadow Database must be marked as shki-owned:
COMMENT ON DATABASE shki_shadow IS 'shki:shadow';
The Shadow Database’s user schemas are reset before every compile, so it must be disposable and dedicated.
Embedded PostgreSQL download fails
Section titled “Embedded PostgreSQL download fails”On first use shki downloads PostgreSQL binaries through the GitHub API. The
request honors HTTPS_PROXY / NO_PROXY, but two things still break it:
- 403 from
api.github.com. GitHub rate-limits unauthenticated API calls per source IP, and everyone behind a corporate proxy shares one IP, so the limit is often already exhausted. SetGITHUB_TOKEN(any token, no scopes needed) and shki sends it as a bearer token, which raises the limit to 5000/hour. A 403 can also come from a proxy that blocks non-browser user agents; the same token does not help there. - No GitHub API access at all. Download the release archive in a browser
(or on another machine) and install it with
shki shadow install. Once a matching version is installed, shki makes no network request.
Either way, shadow_database_url pointing at your own disposable PostgreSQL
bypasses the embedded server entirely.
An extension isn’t available in the Shadow Database
Section titled “An extension isn’t available in the Shadow Database”Embedded PostgreSQL ships without extensions like PostGIS and pgvector. If your
Declarative Schema declares one, point shadow_database_url at an external,
shki-owned PostgreSQL image that has it installed.
adopt refuses: live shape differs from the baseline
Section titled “adopt refuses: live shape differs from the baseline”adopt introspects the target and compares it with the committed baseline
Snapshot. Drift means the environment isn’t actually at the baseline. Either
reconcile the database, or override with --force once you’re satisfied the
difference is benign. --dry-run shows what it would validate and apply.
A shki: directive is rejected
Section titled “A shki: directive is rejected”Unrecognized shki: directives are hard errors, not silent no-ops, so a typo
surfaces before it reaches production. The supported directive is
shki:no-transaction.
Query codegen fails on a type
Section titled “Query codegen fails on a type”Types the Rust generator renders as String but sqlx cannot decode as String
(NUMERIC, ranges, network, geometric, and interval types) need a
[codegen.type_overrides] entry mapping them to a compatible Rust type.