Skip to content

SQLITE_CANTOPEN should be classified as transient, not fatal (kills LaunchAgent) #34678

@mrchris-ai

Description

@mrchris-ai

Problem

SQLITE_CANTOPEN errors cause the gateway process to exit when running as a LaunchAgent on macOS. The same error is survived in terminal mode because it's caught by local try/catch handlers, but when it escapes to the global unhandledRejection handler, it falls through to process.exit(1) because it's not in any safe-list.

This creates a crash loop under launchd: crash → restart → crash → throttle → silent death.

Root Cause

In src/infra/unhandled-rejections.ts (compiled to audio-transcription-runner-*.js), the error classification has:

  • FATAL_ERROR_CODES → exit(1)
  • CONFIG_ERROR_CODES → exit(1)
  • TRANSIENT_NETWORK_CODES → log and continue
  • Everything else → exit(1)

SQLite transient errors (SQLITE_CANTOPEN, SQLITE_BUSY, SQLITE_LOCKED, SQLITE_IOERR) are not in any safe-list. They fall through to the catch-all process.exit(1).

Proposed Fix

Add a TRANSIENT_SQLITE_CODES set (or add to the existing transient set):

const TRANSIENT_SQLITE_CODES = new Set([
  "SQLITE_CANTOPEN",
  "SQLITE_BUSY", 
  "SQLITE_LOCKED",
  "SQLITE_IOERR"
]);

And check it in installUnhandledRejectionHandler alongside isTransientNetworkError.

Environment

Workaround

Manually patching the compiled dist files to add SQLite codes to TRANSIENT_NETWORK_CODES. This survives until the next openclaw update.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions