musistudio/claude-code-router · warning

[backend:${ownerId}] SQLite store close failed: ${formatErro

Error message

[backend:${ownerId}] SQLite store close failed: ${formatError(error)}

What it means

Emitted by BackendService.stopOwner when closing one of an owner's SQLite stores throws. Each store owned by the plugin/owner being stopped is closed in a loop; a throw from store.close() (e.g. an unclosed prepared statement, busy database, or I/O error during checkpoint) is caught per-store, logged, and shutdown continues for the remaining stores. Shutdown never aborts because of it.

Source

Thrown at packages/core/src/plugins/backend-service.ts:124

    if (options.migrate) {
      await options.migrate(database);
      store.persist();
    }
    return store;
  }

  async stopOwner(ownerId: string): Promise<void> {
    const backends = this.backends.filter((backend) => backend.ownerId === ownerId);
    this.backends = this.backends.filter((backend) => backend.ownerId !== ownerId);
    await Promise.all(backends.map((backend) => closeServer(backend.server)));

    const sqliteStores = this.sqliteStores.filter((store) => store.ownerId === ownerId);
    this.sqliteStores = this.sqliteStores.filter((store) => store.ownerId !== ownerId);
    for (const store of sqliteStores) {
      try {
        store.close();
      } catch (error) {
        console.warn(`[backend:${ownerId}] SQLite store close failed: ${formatError(error)}`);
      }
    }
  }

  async stopAll(): Promise<void> {
    const ownerIds = new Set([
      ...this.backends.map((backend) => backend.ownerId),
      ...this.sqliteStores.map((store) => store.ownerId)
    ]);
    await Promise.all([...ownerIds].map((ownerId) => this.stopOwner(ownerId)));
  }
}

class SqliteStoreImpl implements SqliteStore {
  constructor(
    readonly ownerId: string,
    readonly dbFile: string,
    readonly database: SqlDatabase

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Free disk space and verify write permissions on the SQLite state directory.
  2. Ensure no other process opens the same SQLite files (single-owner access).
  3. If it happens on every shutdown after a crash, stop everything, delete/recreate the affected store file (data loss limited to that store), and restart.
  4. Upgrade the core package — newer SQLite drivers checkpoint more gracefully on close.
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Calling stopAll, stop, rollbackConfiguredPluginLoad, or stopBrowserWebSearchMcpServers while a SQLite database file is locked, on a read-only/full disk, or when the store has open cursors/statements that make close() throw.

Common situations: Disk full or permissions changed under the state directory; another process (or an in-flight query) holds the SQLite file; plugin rollback racing with active writes during a config reload.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/8ecaf4ee58f53594. Report an issue: GitHub.