JuliusBrussee/caveman · error

conflicting committed and pending integration journals for $

Error message

conflicting committed and pending integration journals for ${agent}; refusing recovery

What it means

Interrupted native installs are recovered using a pending journal plus a committed journal per agent. Recovery expects either a pending journal alone (interrupted install) or a committed journal alone; finding BOTH with different contents is a state the recovery logic cannot interpret safely, so it refuses rather than guess. Identical journals are benign (the pending copy is deleted and recovery is skipped).

Source

Thrown at packages/cli/src/index.ts:6899

    return value?.schema_version === 1 && value.agent === agent && Array.isArray(value.operations) ? value : undefined;
  } catch { return undefined; }
}

function readNativeJournal(agent: string): NativeJournal | undefined {
  return readNativeJournalAt(nativeJournalPath(agent), agent);
}

function readPendingNativeJournal(agent: string): NativeJournal | undefined {
  return readNativeJournalAt(nativePendingJournalPath(agent), agent);
}

function recoverPendingNativeInstallUnlocked(agent: NativeAgent): boolean {
  const pending = readPendingNativeJournal(agent);
  if (!pending) return false;
  const committed = readNativeJournal(agent);
  if (committed) {
    if (JSON.stringify(committed) !== JSON.stringify(pending)) {
      throw new Error(`conflicting committed and pending integration journals for ${agent}; refusing recovery`);
    }
    unlinkSync(nativePendingJournalPath(agent));
    return false;
  }
  const current = pending.operations.map((operation) => ({ file: operation.file, bytes: fileBytes(operation.file) }));
  const restored = pending.operations.map((operation) => {
    const before = nativeBackupBytes(operation);
    const now = fileBytes(operation.file);
    const isInstalled = Boolean(now && bytesHash(now) === operation.after_sha256);
    const isBefore = operation.before_exists
      ? Boolean(now && operation.before_sha256 && bytesHash(now) === operation.before_sha256)
      : now === null;
    if (!isInstalled && !isBefore) {
      throw new Error(`${operation.file} changed during interrupted ${agent} install; refusing recovery`);
    }
    return { file: operation.file, bytes: before };
  });
  try {

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Inspect both journal files for the agent and determine which reflects reality on disk.
  2. If the committed journal is authoritative, delete the pending journal file.
  3. If the pending journal is authoritative (install never completed), remove the committed journal and re-run recovery.
  4. If unsure, uninstall and reinstall the agent integration to rebuild consistent state.

Example fix

# before: conflicting journals
ls ~/.caveman/*/native/*/journal*   # both committed and pending present
# after: keep the committed journal, drop the pending copy
rm ~/.caveman/.../claude.pending.json && caveman install claude
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync, existsSync } from "node:fs";

function journalsConsistent(pending: string, committed: string): boolean {
  if (!existsSync(pending) || !existsSync(committed)) return true;
  try {
    return readFileSync(pending, "utf8") === readFileSync(committed, "utf8");
  } catch {
    return false;
  }
}

Try / catch

try {
  runRecovery(agent);
} catch (e) {
  if (e instanceof Error && e.message.includes("conflicting committed and pending")) {
    // stop automation; surface state paths to the operator for manual reconciliation
    throw new FatalStateError(agent);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the install/recovery path when both nativePendingJournalPath(agent) and the committed journal exist and JSON.stringify comparison of the two journals differs — typically after a crash between committing and pending-journal cleanup, or after manual edits to the state directory.

Common situations: Process killed at exactly the wrong moment during a native install, users hand-editing or restoring partial copies of the caveman state directory, or downgrades/ upgrades that changed the journal schema between writes.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/5b9d943df5e1ece9. Report an issue: GitHub.