Summary
When the pre-readiness startup-migration gate (introduced in #101881) refuses to report the gateway ready, the process prints the correct error and then dies with SIGSEGV (exit code 139) instead of exiting non-zero. Under any supervisor that restarts on exit (systemd Restart=always, k8s, Fly machines), a recoverable "fix your state and reboot" condition becomes a machine-killing crash loop.
Environment
- openclaw 2026.7.1 (GHCR image, digest
sha256:6a31d44b…), gateway mode
- State dir on a persistent volume, process running as an unprivileged user
- Telegram channel + acpx and several other plugins configured
- Fly.io firecracker VM; supervisor restarts the machine when the entrypoint exits
What happens
On boot, the migration gate fails (two independent triggers reproduced this, see below), the CLI prints:
[openclaw] Could not start the CLI.
[openclaw] Reason: OpenClaw startup migrations did not complete cleanly; refusing to report the gateway ready.
[openclaw] Try: openclaw doctor
and the process then terminates with exit code 139 (SIGSEGV; oom_killed=false per the VM event log). The supervisor restarts it, the same state condition re-trips the gate, and the machine crash-loops. We hit this on four boots across two upgrade attempts (2026-07-14 and 2026-07-17), with two different underlying migration failures:
- a leftover legacy plugin-state sidecar (
plugin-state/state.sqlite) whose target namespace in shared state was already populated
- a plugin payload smoke-check failure (
EACCES on one plugin's package.json)
So this is the shared failure path, not a property of one trigger.
One data point on where the segfault lives
In an isolated reproduction of trigger 2 with the Telegram channel disabled and the gateway run directly under bash, the same migration failure exited with code 1, cleanly. The segfault reproduced only with the full channel set configured. That suggests the crash is a teardown race after the refusal (channels/sidecars initialized, then torn down on the failure path), not the gate itself.
Expected
Exit 1 after printing the reason. The error message itself is good; the exit signal is the problem.
Impact
Any stateful condition the gate dislikes takes down production deployments in a restart loop rather than leaving a diagnosable dead process. The two triggers above are filed separately: #109832 (redundant sidecar blocks the gate) and #109833 (plugin EACCES classified as migration failure).
Summary
When the pre-readiness startup-migration gate (introduced in #101881) refuses to report the gateway ready, the process prints the correct error and then dies with SIGSEGV (exit code 139) instead of exiting non-zero. Under any supervisor that restarts on exit (systemd
Restart=always, k8s, Fly machines), a recoverable "fix your state and reboot" condition becomes a machine-killing crash loop.Environment
sha256:6a31d44b…), gateway modeWhat happens
On boot, the migration gate fails (two independent triggers reproduced this, see below), the CLI prints:
and the process then terminates with exit code 139 (SIGSEGV;
oom_killed=falseper the VM event log). The supervisor restarts it, the same state condition re-trips the gate, and the machine crash-loops. We hit this on four boots across two upgrade attempts (2026-07-14 and 2026-07-17), with two different underlying migration failures:plugin-state/state.sqlite) whose target namespace in shared state was already populatedEACCESon one plugin'spackage.json)So this is the shared failure path, not a property of one trigger.
One data point on where the segfault lives
In an isolated reproduction of trigger 2 with the Telegram channel disabled and the gateway run directly under bash, the same migration failure exited with code 1, cleanly. The segfault reproduced only with the full channel set configured. That suggests the crash is a teardown race after the refusal (channels/sidecars initialized, then torn down on the failure path), not the gate itself.
Expected
Exit 1 after printing the reason. The error message itself is good; the exit signal is the problem.
Impact
Any stateful condition the gate dislikes takes down production deployments in a restart loop rather than leaving a diagnosable dead process. The two triggers above are filed separately: #109832 (redundant sidecar blocks the gate) and #109833 (plugin EACCES classified as migration failure).