Skip to content

[Bug]: Mac app still writes legacy logs/config-health.json every ~3s, permanently conflicting with the config_health_entries SQLite migration #98917

Description

@P51moustache

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

The macOS app still persists its config-corruption baseline to the retired legacy path ~/.openclaw/logs/config-health.json (rewritten atomically every ~2–3s while the app runs), while Node core ≥2026.6.x owns config-health state in the shared SQLite config_health_entries table — so migrateLegacyConfigHealth reports a conflict warning on every CLI/gateway bootstrap on any machine running the Mac app, and doctor --fix can never clear it.

Steps to reproduce

  1. Run OpenClaw.app (macOS app, 2026.6.10) alongside openclaw 2026.6.11 CLI/gateway (npm global) on macOS.
  2. Run any CLI command (e.g. openclaw status) or start the gateway.
  3. Observe on every bootstrap:
    [state-migrations] Legacy state migration warnings: - Left legacy config health state in place because 1 entry conflicts with shared SQLite state: /Users/…/.openclaw/logs/config-health.json
  4. Delete the JSON while the app runs → it reappears within ~3s (live inode churn observable via stat).

Expected behavior

After core moved config-health to SQLite (src/config/io.health-state.ts), no component writes the legacy JSON path; the migration archives the file once and never warns again — per repo policy that legacy state files are migration debt with a single owner.

Actual behavior

The Swift writer still exists at repo HEAD: apps/macos/Sources/OpenClaw/OpenClawConfigFile.swift:8,480-511. The migration's conflict check (configHealthComparable, src/infra/state-migrations.ts:2090-2195; identical in installed dist state-migrations-CDz8cSvR.js:1706-1772) compares string-serialized tuples that can never match across the two writers: Foundation JSONSerialization key order + escaped slashes, Swift ctimeMs=creationDate vs Node ctime, rolling observedAt refreshed every write, and the Swift side never writes lastPromotedGood. Substantively both stores agree (identical config SHA-256 / bytes / inode) — a pure serialization/ownership mismatch, permanent while the app runs.

OpenClaw version

CLI/gateway 2026.6.11 (e085fa1); Mac app 2026.6.10; Swift writer confirmed present at repo HEAD (2026-06-30)

Operating system

macOS 15.6 (Darwin 24.6.0)

Install method

npm global (Homebrew node) + Mac app

Model

n/a — state-migration bug, model-independent

Provider / routing chain

n/a

Logs

[state-migrations] Legacy state migration warnings:
- Left legacy config health state in place because 1 entry conflicts with shared SQLite state: /Users/zach/.openclaw/logs/config-health.json

Evidence the Mac app is the writer: JSON exhibits Foundation formatting (" : " separators, \/ escapes, sorted keys); the string config-health.json is present in /Applications/OpenClaw.app/Contents/MacOS/OpenClaw; file mtime/inode churn every ~3s while the app runs and stops when it quits.

Impact and severity

Additional information

Workaround: quit the Mac app and delete/rename the JSON — the warning clears until the app relaunches. Suggested fix direction: the Mac app should stop persisting the baseline to the legacy path (or write via gateway/SQLite), letting the existing migration archive the file once.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.no-staleExclude from stale automation

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions