Skip to content

bug(runtime-host): legacy source messages block Desktop startup after upgrade #3902

Description

@Sun-GLiang

What happened

After upgrading a workspace created by an older Maka build, Desktop can no longer start.

The Runtime Host enters the recovering state, then exits with:

SessionMetadataConflictError: Message admission does not exist

Desktop reports:

Runtime Host failed while recovering this workspace.
Diagnostic code: INTERNAL_STARTUP_FAILURE

Every launch method using the same default workspace fails because the Runtime Host never reaches ready.

Actual result: A legacy message record causes recovery to fail, making the entire workspace unbootable.

Expected result: Runtime Host recovery should remain compatible with workspaces created before durable message admissions were introduced. Legacy messages should be migrated or recovered without blocking startup.

How to reproduce

  1. Use a Maka build from before 24a97c54e / feat: durable message lifecycle from admission to execution #3721.
  2. Create and complete a Turn whose Root admission contains sourceMessages.
  3. Confirm the source message was not persisted in:
    • message_admissions
    • cancelled_message_admissions
    • session_messages
  4. Upgrade to the current build.
  5. Ensure the older Runtime Host has exited.
  6. Start Maka Desktop.
  7. Observe that the new Runtime Host enters recovering and exits with INTERNAL_STARTUP_FAILURE.

The issue reproduced consistently across four startup attempts.

A deterministic storage fixture can reproduce it by creating:

  • A terminal Agent Run.
  • A Root Turn admission with one source message.
  • No corresponding message admission, cancellation, or transcript row.

Environment

  • Maka version or commit: 0.2.0, dev build at 4cda7d8
  • OS and version: macOS 15.6 / Darwin 24.6.0, arm64
  • Surface: Desktop / Runtime Host
  • Electron: 43.4.1
  • Node.js: 24.18.1
  • Runtime Host compatibility epoch:
    • Legacy workspace Host: 44
    • Current build: 50

Logs, screenshots, or additional context

The direct candidate startup stack is:

AggregateError: Runtime Host startup failed and shutdown did not complete cleanly
  [cause]: SessionMetadataConflictError: Message admission does not exist
    at SqliteSessionMetadataStore.markMessagesHandedOff
    at SqliteSessionStore.markMessagesHandedOff
    at HostMessageCoordinator.materializeMessageHandoffsForRun
    at RootTurnCoordinator.recover
    at execution-composition executions recovery

The affected recovery path is:

RootTurnCoordinator.recover()
-> terminal snapshot with sourceMessages
-> HostMessageCoordinator.materializeMessageHandoffsForRun()
-> SqliteSessionMetadataStore.markMessagesHandedOff()
-> no message_admissions row
-> no session_messages row
-> SessionMetadataConflictError

The observed database contained two legacy Root Turn admissions created before #3721. Each referenced one source message, but neither message existed in:

message_admissions
cancelled_message_admissions
session_messages

The database itself is healthy:

PRAGMA quick_check: ok
Foreign-key violations: 0

dist was verified as fresh, and Runtime Host recovery succeeds against a clean data root. This isolates the failure to legacy operational-data compatibility.

Root cause

Commit 24a97c54e introduced durable message admission and added terminal recovery materialization:

if (isTerminalSnapshot(snapshot) && admission.sourceMessages.length > 0) {
  await messages.materializeMessageHandoffsForRun(...);
}

markMessagesHandedOff() requires each source message to exist either as a durable message admission or as an already materialized transcript message.

Workspaces created before this lifecycle was introduced can contain authoritative Root source messages without either representation. No migration or legacy recovery path handles that state, so one historical Turn prevents the entire Runtime Host from starting.

Proposed fix

During startup recovery, support pre-#3721 Root admissions whose source messages have no durable message-admission row.

Use the authoritative source message stored in the Root admission to safely backfill or materialize the missing transcript message. Preserve exactly-once behavior and do not silently discard historical messages.

Suggested acceptance scenarios

  • Seed a terminal legacy Root admission with one source message and no corresponding message-admission or transcript row.
  • Start Runtime Host recovery and verify it reaches ready.
  • Verify the legacy source message is materialized exactly once.
  • Restart the Host and verify recovery remains idempotent.
  • Preserve strict conflict detection for genuinely inconsistent modern admission records.
  • Confirm existing durable message-admission recovery tests continue to pass.
  • Confirm upgraded workspaces no longer fail with INTERNAL_STARTUP_FAILURE.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions