Submit an issue View all issues Source
MIR-1289

`post_import` in app.toml is parsed and documented but never executed (silent no-op)

Done public Bug
phinze phinze Opened Jul 2, 2026 Updated Jul 13, 2026

Summary

post_import is a documented, parsed, and validated app.toml key, but nothing in the runtime ever executes it. Deploys silently skip it and report success. For its headline use case — database migrations — the schema is never updated, the deploy looks clean, and the app breaks at runtime.

Most urgent piece (why this is High): the docs actively tell users to use post_import for migrations, so right now it's a silent trap. Independent of the larger "wire it or retire it" decision below, we should pull it from the docs promptly.

Environment

  • Cluster: selkie · miren CLI HEAD:794dca1 (v0.10.0-20-g794dca1c, built 2026-06-26)
  • App: posse-party (Rails, running the upstream ghcr.io/searlsco/posse_party image via a one-line FROM Dockerfile)
  • .miren/app.toml included: post_import = "cd /rails && ./bin/rake db:migrate"

Repro / what happened

Across five deploys the migration never ran. miren logs system shows no migrate/import activity. The web service booted (its schema check passed), but the worker crash-looped on relation "solid_queue_recurring_tasks" does not exist. Running ./bin/rake db:migrate by hand in a miren app run sandbox created the tables (28 migrations); a restart then brought the worker up clean. The only thing missing was post_import actually firing.

Root cause (runtime @ 794dca1)

  • The PostImport field is defined (appconfig/appconfig.go:90), allow-listed as a valid top-level key (appconfig/configerror.go:343), and documented with precise semantics — "runs after a new version is imported but before it receives traffic. Commonly used for database migrations" (docs/docs/app-toml.md:18,74, docs/docs/terminology.md:99-101).
  • But the Go identifier PostImport is referenced exactly once in the entire repo — its own declaration. Nothing reads ac.PostImport. AppConfig is threaded through the build saga as the app_config saga field, so the value reaches the server; the field is simply never consumed.
  • The build saga's action DAG (servers/build/build_saga.go:677-678) is create-versionprovision-addonsfinalize. There is no post-import / migration step anywhere in that sequence.
  • git blame: the field was added 2026-02-01 in ac6e0bfd ("Add auto building") and has never been wired to an executor since.

Impact

Silent, data-layer failure mode: the deploy reports success while a documented step is skipped. Because the docs point users at post_import for migrations, following them leads straight into it. Worst case is a partially-migrated app that boots and then fails on the missing schema (as ours did).

Wire it or retire it

The current state — documented + validated + inert — is the worst option. Two ways out:

  1. Wire it: execute post_import as a gated step between provision-addons and traffic activation; fail the deploy on non-zero exit, matching the documented "before it receives traffic" contract.
  2. Retire it: if MIR-853 (one-shot/scheduled service types, RFD 79) is the intended path for deploy-time commands — which seems likely — drop post_import entirely and reject/warn on the key.

Regardless of which we choose, the immediate step is to remove post_import from the docs (docs/docs/app-toml.md:18,74 and docs/docs/terminology.md:99-101) so it stops trapping users while the larger decision plays out. That's the High-priority piece; the wire-vs-retire call can follow.

Related

  • MIR-853 — one-shot/scheduled service types; the likely successor for deploy-time migrations. post_import looks like an early stab at the same need.
  • MIR-1016 — sibling class: app.toml input silently mishandled while the deploy reports success.