Skip to content

gateway: startup-migration failure path exits with SIGSEGV (139) instead of a clean non-zero exit, causing supervisor crash loops #109831

Description

@jonasserry

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:

  1. a leftover legacy plugin-state sidecar (plugin-state/state.sqlite) whose target namespace in shared state was already populated
  2. 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).

Metadata

Metadata

Assignees

Labels

P0Emergency: data loss, security bypass, crash loop, or unusable core runtime.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.impact:ux-release-blockerA non-technical user is blocked without terminal, logs, config, or support.issue-rating: 🦪 silver shellfishThin issue quality; more reproduction proof or environment detail is needed.

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions