Skip to content

Fix container image upgrade migrations before gateway readiness#101881

Merged
sallyom merged 2 commits into
openclaw:mainfrom
sallyom:container-upgrade
Jul 8, 2026
Merged

Fix container image upgrade migrations before gateway readiness#101881
sallyom merged 2 commits into
openclaw:mainfrom
sallyom:container-upgrade

Conversation

@sallyom

@sallyom sallyom commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #98565.

Replacing a Docker, Podman, or Kubernetes container image while preserving the mounted OpenClaw state volume could start openclaw gateway run directly and skip the startup repair/convergence work normally reached through openclaw update or openclaw doctor --fix. That let a gateway become healthy while state and plugin install metadata still reflected the previous image.

Why This Change Was Made

  • Add a shared-state startup migration checkpoint keyed to the current OpenClaw version.
  • Gate foreground gateway startup on that checkpoint, while leaving probes like gateway health alone.
  • Run startup state migrations and post-core plugin convergence under a shared SQLite lease before readiness.
  • Heartbeat the lease during long startup work and verify lease ownership before recording the checkpoint.
  • Keep checkpoint/lease acquisition behind the gateway startup guard, and avoid requiring the full shared-state schema to be canonical before doctor-style state repair can run.
  • Fail closed for invalid config/state, startup migration warnings, lease loss, or plugin convergence errors; surface nonblocking plugin repair warnings without preventing startup.
  • Document container image upgrade repair commands for Docker, Podman, and Kubernetes.

User Impact

Routine container image upgrades with the same mounted state should converge automatically before the gateway reports healthy. If repair cannot complete safely, startup fails closed instead of serving with half-upgraded state; operators can run openclaw doctor --fix with the same image and mounted state volume, then restart. Nonblocking plugin repair warnings are logged but do not stop startup, matching the current openclaw update behavior more closely.

Evidence

  • node scripts/crabbox-wrapper.mjs run --provider blacksmith-testbox --timing-json -- pnpm test src/infra/startup-migration-checkpoint.test.ts src/commands/doctor-config-preflight.state-migration.test.ts passed on Testbox tbx_01kwzaarst9n88z2rxf30dz6s9: 6 checkpoint tests and 15 startup preflight tests.
  • node scripts/crabbox-wrapper.mjs run --provider blacksmith-testbox --timing-json -- pnpm check:changed -- src/infra/startup-migration-checkpoint.ts src/infra/startup-migration-checkpoint.test.ts src/commands/doctor-config-preflight.ts src/commands/doctor-config-preflight.state-migration.test.ts src/state/openclaw-state-db.ts passed on Testbox tbx_01kwzade1d7rne5f0tgatwkaf3.
  • Earlier full touched-surface check including docs passed on Testbox tbx_01kwz5v7dp5vtycwmthhnw9jyw.
  • Local Podman Crabbox proof: provider=local-container, runtime podman, lease cbx_3f10582cbbf0, Ubuntu 26.04, exit 0. A real pnpm openclaw gateway run --dev --allow-unconfigured --auth none --port 19565 reached /health; checkpoint moved from before=2026.6.10 to after=2026.6.11; health={"ok":true,"status":"live"}.
  • .agents/skills/autoreview/scripts/autoreview --mode local clean after the narrowed startup-blocking policy and guard-order fixes.
  • .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main clean on the full PR diff after committing.
  • git diff --check passed.
  • node scripts/check-docs-mdx.mjs docs README.md docs/install/docker.md docs/install/updating.md passed.
  • node scripts/format-docs.mjs --check docs/install/docker.md docs/install/updating.md passed.
  • node scripts/docs-link-audit.mjs -- docs/install/docker.md docs/install/updating.md still reports existing unrelated ClawHub route-link failures; this PR's new /install/docker#upgrading-container-images link is present in the changed docs.

No Agent Transcript section included.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation cli CLI command changes commands Command implementations docker Docker and sandbox tooling size: L maintainer Maintainer-authored PR labels Jul 7, 2026
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 8, 2026, 1:10 PM ET / 17:10 UTC.

Summary
The PR adds a shared-state startup migration checkpoint and lease for foreground gateway startup, runs state migration and post-core plugin convergence before readiness, and documents Docker/Podman/Kubernetes recovery commands.

PR surface: Source +392, Tests +427, Docs +68. Total +887 across 13 files.

Reproducibility: yes. The linked issue includes a live official-image 2026.6.10 to 2026.6.11 container swap, and current main's Docker command enters the gateway path without a versioned startup checkpoint; I did not rerun the container flow in this read-only review.

Review metrics: 3 noteworthy metrics.

  • Persistent Startup State: 1 checkpoint key, 1 lease scope added. The checkpoint and lease become durable shared-state upgrade compatibility contracts.
  • Foreground Gateway Gate: 2 command forms gated. Bare gateway and gateway run can now converge or fail before readiness while probe subcommands remain ungated by the checkpoint.
  • Startup Convergence Path: 1 post-core convergence call added. The PR moves existing plugin convergence behavior into the gateway readiness path, which maintainers should notice before merge.

Stored data model
Persistent data-model change detected: database schema: src/state/openclaw-state-db.ts, migration/backfill/repair: docs/cli/doctor.md, migration/backfill/repair: docs/install/docker.md, migration/backfill/repair: docs/install/updating.md, migration/backfill/repair: src/cli/program/config-guard.test.ts, migration/backfill/repair: src/cli/program/config-guard.ts, and 7 more. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #98565
Summary: This PR is the open candidate fix for the canonical container image upgrade readiness and migration issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

Risk before merge

  • [P1] Existing container deployments may now fail readiness or restart-loop during unresolved startup migration warnings, invalid config, lease loss, or plugin convergence failures instead of serving stale state.
  • [P1] Gateway readiness now depends on durable shared-state checkpoint writes and post-core plugin convergence before the service reports healthy, changing the upgrade contract for container operators.
  • [P1] The open gateway-preflight PR at improve: skip Gateway migration preflight without legacy state #96234 touches the same startup guard surface, so landing order should preserve this checkpoint requirement.

Maintainer options:

  1. Accept The Readiness Contract (recommended)
    Maintainers can accept that container gateway startup may converge or fail closed before readiness to avoid serving half-upgraded state.
  2. Narrow Startup Convergence
    Revise the branch so startup records the checkpoint and runs state migrations only, leaving package repair to explicit doctor or update commands.
  3. Pause This Landing Path
    Hold or close this PR if maintainers decide the broader upgrade convergence contract should be designed separately from foreground gateway startup.

Next step before merge

  • [P2] Protected maintainer handling and the compatibility/availability policy choice require human acceptance; no narrow automated repair remains after the latest warning-blocking fix.

Maintainer decision needed

  • Question: Should foreground container gateway startup run state migrations plus post-core plugin convergence before readiness, including configured-plugin package repair when the existing convergence path requires it?
  • Rationale: The patch fixes a real false-ready upgrade path, but it intentionally moves upgrade convergence into gateway startup and can change existing operator availability behavior.
  • Likely owner: openperf — openperf owns the closest recent gateway startup migration boundary that this PR extends.
  • Options:
    • Accept Startup Convergence (recommended): Proceed with startup performing safe convergence work before readiness, with the documented fail-closed repair path for operators.
    • Limit Startup To State Gating: Keep the version checkpoint and state migration readiness gate, but leave configured-plugin package repair to explicit update or doctor flows.
    • Keep Convergence Explicit: Do not move post-core convergence into startup; instead fail with a clear repair command when a version transition is detected.

Security
Cleared: No concrete security or supply-chain defect was found in the diff; the package-repair timing change is captured as compatibility and availability merge risk.

Review details

Best possible solution:

Merge only after a maintainer accepts the converge-or-fail-closed foreground gateway startup policy and exact-head CI/proof remain green for the startup, shared-state, plugin convergence, and docs surfaces.

Do we have a high-confidence way to reproduce the issue?

Yes. The linked issue includes a live official-image 2026.6.10 to 2026.6.11 container swap, and current main's Docker command enters the gateway path without a versioned startup checkpoint; I did not rerun the container flow in this read-only review.

Is this the best way to solve the issue?

Yes, if maintainers accept the startup policy. The patch uses the existing foreground gateway preflight boundary, reuses post-core convergence, and records a shared-state checkpoint; a state-only gate would leave the plugin convergence failure mode unresolved.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 8fa83d27420b.

Label changes

Label justifications:

  • P1: The PR targets a real container-upgrade regression where the gateway can report healthy while migration or plugin repair remains pending.
  • merge-risk: 🚨 compatibility: Existing container upgrade workflows may now fail closed, require explicit repair, or change readiness behavior during upgrade instead of continuing to serve.
  • merge-risk: 🚨 availability: Gateway readiness can now be blocked by startup migration, lease, invalid-config, or plugin convergence failures before the service becomes healthy.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Sufficient: the PR body includes focused Testbox runs and a real Podman container gateway run showing /health live with the checkpoint moving from 2026.6.10 to 2026.6.11 after the fix.
  • proof: sufficient: Contributor real behavior proof is sufficient. Sufficient: the PR body includes focused Testbox runs and a real Podman container gateway run showing /health live with the checkpoint moving from 2026.6.10 to 2026.6.11 after the fix.
Evidence reviewed

PR surface:

Source +392, Tests +427, Docs +68. Total +887 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 4 490 98 +392
Tests 3 436 9 +427
Docs 6 69 1 +68
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 13 995 108 +887

What I checked:

  • Repository policy makes this merge-sensitive: Root policy treats migrations, startup checks, fail-closed behavior, stricter validation, and new operator action as compatibility/upgrade-sensitive merge risk even with green CI. (AGENTS.md:31, 8fa83d27420b)
  • Current container entrypoint starts the gateway directly: Current main's Docker image healthcheck probes /healthz and the default command is node openclaw.mjs gateway, so image replacement enters foreground gateway startup rather than update or doctor. (Dockerfile:355, 8fa83d27420b)
  • Current main lacks a versioned startup checkpoint: Current main runs doctor config preflight for gateway startup with state migration enabled but without any startup migration checkpoint requirement. (src/cli/program/config-guard.ts:211, 8fa83d27420b)
  • PR gates foreground gateway startup only: At the PR head, bare gateway and gateway run add requireStartupMigrationCheckpoint, while probe subcommands such as gateway health do not add that checkpoint flag. (src/cli/program/config-guard.ts:173, 749f839cbec6)
  • PR records checkpoint only after clean startup work: The PR acquires the startup checkpoint path, accumulates migration warnings, runs post-core plugin convergence only for a valid clean snapshot, blocks on warnings or blockers, then records the checkpoint under the lease. (src/commands/doctor-config-preflight.ts:314, 749f839cbec6)
  • PR adds durable checkpoint and lease state: The PR stores a startup-migrations app-version row and a global startup-migrations lease with a five-minute TTL in shared SQLite state. (src/infra/startup-migration-checkpoint.ts:19, 749f839cbec6)

Likely related people:

  • openperf: Authored the merged gateway fast-path startup migration/bootstrap PR that this PR extends into a versioned container upgrade checkpoint. (role: recent gateway startup migration contributor; confidence: high; commits: f799a5817cc9, ae1f5310d3e9, 8bb16f716c04; files: src/cli/gateway-cli/pre-bootstrap.ts, src/cli/program/config-guard.ts, src/commands/doctor-config-preflight.ts)
  • fuller-stack-dev: Authored the merged package doctor warning/update work adjacent to the post-core convergence path now invoked before gateway readiness. (role: recent update and package convergence contributor; confidence: medium; commits: 328b5f17a78a, 377924d03129, 408dcbeeee89; files: src/cli/update-cli/post-core-plugin-convergence.ts, src/infra/package-update-steps.ts, src/commands/doctor/shared/missing-configured-plugin-install.ts)
  • jacobtomlinson: Reported the canonical container-upgrade issue and authored the merged Mattermost configured-plugin activation repair that exposed the broader readiness gap. (role: adjacent configured-plugin repair contributor; confidence: medium; commits: b8a010e1971b; files: src/config/plugin-auto-enable.shared.ts, src/config/plugin-auto-enable.channels.test.ts)
  • vincentkoc: Merged the gateway fast-path startup migration/bootstrap PR, and local blame on the current startup guard points at the merged boundary commit in current main. (role: merger and recent gateway-startup reviewer; confidence: medium; commits: df521a645977, 94da0a9813; files: src/cli/program/config-guard.ts, src/cli/run-main.ts, src/cli/gateway-cli/pre-bootstrap.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (14 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-08T11:33:36.830Z sha 59132f9 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-08T11:46:15.787Z sha 59132f9 :: found issues before merge. :: [P2] Align the plugin-repair startup docs
  • reviewed 2026-07-08T12:13:46.335Z sha 6731f57 :: needs changes before merge. :: [P2] Align the plugin-repair startup docs
  • reviewed 2026-07-08T12:21:30.857Z sha 6731f57 :: needs changes before merge. :: [P2] Align the plugin-repair startup docs
  • reviewed 2026-07-08T12:35:06.199Z sha 4132e14 :: needs changes before merge. :: [P2] Describe package repair accurately
  • reviewed 2026-07-08T12:42:27.699Z sha 4132e14 :: needs changes before merge. :: [P2] Describe package repair accurately
  • reviewed 2026-07-08T14:04:31.182Z sha 32dd2ee :: needs maintainer review before merge. :: none
  • reviewed 2026-07-08T17:02:19.121Z sha 749f839 :: needs maintainer review before merge. :: none

@sallyom
sallyom marked this pull request as ready for review July 7, 2026 21:12
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 7, 2026
@sallyom
sallyom force-pushed the container-upgrade branch from 475d6db to 59132f9 Compare July 8, 2026 11:27
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 8, 2026
@sallyom
sallyom force-pushed the container-upgrade branch 2 times, most recently from 6731f57 to 4132e14 Compare July 8, 2026 12:29
@openclaw-barnacle openclaw-barnacle Bot added the gateway Gateway runtime label Jul 8, 2026
@sallyom
sallyom force-pushed the container-upgrade branch from 4132e14 to 32dd2ee Compare July 8, 2026 13:55
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 8, 2026

@jacobtomlinson jacobtomlinson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR is pointed at the right layer: foreground gateway / gateway run gets a version checkpoint, a shared-state lease, state migrations, and post-core plugin convergence before readiness. That matches the broad intent of #98565.

Findings:

  • [blocking] Startup records the version checkpoint even when configured-plugin repair did not complete. In runStartupUpgradeConvergence, convergence warnings only become blockers when convergence.errored is true (src/commands/doctor-config-preflight.ts:132, src/commands/doctor-config-preflight.ts:320). But runPostCorePluginConvergence treats repair/install failures from repairMissingConfiguredPluginInstalls as warnings and sets errored only for payload smoke failures (src/cli/update-cli/post-core-plugin-convergence.ts:131, src/cli/update-cli/post-core-plugin-convergence.ts:173). The new test codifies that behavior by recording the startup checkpoint while plugin repair warnings are present (src/commands/doctor-config-preflight.state-migration.test.ts:329). That means a container image swap can still report healthy after a configured official plugin failed to install/repair, then persist the current OpenClaw version as migrated; future restarts skip the startup convergence pass for that version. That is the same false-ready, half-upgraded state #98565 was meant to close. Please either treat startup plugin repair warnings that represent failed required convergence as readiness blockers, or avoid recording the startup checkpoint until a later startup/doctor pass completes those repairs. Pure informational notices can stay nonblocking, but failed migration/repair work should not be checkpointed as success.

Best-fix verdict: right owner boundary, but too permissive on migration failure semantics. This is not ready until startup convergence failure and checkpointing match the issue intent.

Evidence reviewed: PR head 32dd2ee88a53, current issue #98565 body, Dockerfile:358, src/cli/program/config-guard.ts, src/commands/doctor-config-preflight.ts, src/infra/startup-migration-checkpoint.ts, src/state/openclaw-state-db.ts, src/cli/update-cli/post-core-plugin-convergence.ts, and the added tests/docs. CI is broadly green, but this is a source-level policy/correctness gap rather than a failing-test gap.

sallyom added 2 commits July 8, 2026 12:41
Signed-off-by: sallyom <somalley@redhat.com>
Signed-off-by: sallyom <somalley@redhat.com>
@sallyom
sallyom force-pushed the container-upgrade branch from 32dd2ee to 749f839 Compare July 8, 2026 16:56
@sallyom

sallyom commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Best-fix verdict: right owner boundary, but too permissive on migration failure semantics. This is not ready until startup convergence failure and checkpointing match the issue intent.

Fixed by keeping runPostCorePluginConvergence nonblocking for the updater, but making the startup checkpoint wrapper treat returned convergence warnings as readiness blockers. So gateway now logs the warning, refuses readiness, and does not record the startup migration checkpoint until a later startup/doctor pass completes cleanly.

Covered by the updated regression test in src/commands/doctor-config-preflight.state-migration.test.ts
Autoreview clean locally.

@sallyom

sallyom commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

as a last check before merge, I ran an upgrade and confirmed this in gateway logs and files:

  • openclaw --version: OpenClaw 2026.6.11 (updated from 6.10 using my custom quay.io/sallyom/openclaw:latest built from this PR branch)
  • Startup log showed Auto-migrated legacy state
  • Migrated file exists: /home/node/.openclaw/logs/config-health.json.migrated
  • SQLite checkpoint exists:

{
"meta_key": "startup-migrations",
"role": "global",
"schema_version": 1,
"app_version": "2026.6.11",
"updated_at_utc": "2026-07-08 18:10:41"
}

  • No active startup migration lease remains.
  • /readyz returns 200 {"ready":true,...}

So this shows the new image started against mounted state, ran the startup migration gate, wrote the per-version checkpoint, released the lease, and only then became ready.

@sallyom
sallyom merged commit b81666c into openclaw:main Jul 8, 2026
101 checks passed
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…claw#101881)

* run all 'openclaw upgrade' migrations with container image upgrades

Signed-off-by: sallyom <somalley@redhat.com>

* fix: block gateway startup on plugin repair warnings

Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 9, 2026
…claw#101881)

* run all 'openclaw upgrade' migrations with container image upgrades

Signed-off-by: sallyom <somalley@redhat.com>

* fix: block gateway startup on plugin repair warnings

Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes commands Command implementations docker Docker and sandbox tooling docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XL status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Container image upgrades skip openclaw upgrade migrations before gateway startup

2 participants