JuliusBrussee/caveman · error · Error

pending ${label} transaction is malformed: ${(error as Error

Error message

pending ${label} transaction is malformed: ${(error as Error).message}

What it means

A wrapper thrown around any error raised inside the journal validation/decoding try-block (including errors 21, 22, 24, 26, 27 from decodePendingBytes and cross-field checks). It prefixes the original message with 'pending <label> transaction is malformed:' so callers know the pending journal for that transaction label is unusable and recovery was refused.

Source

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

      || optionalBytesHash(markerAfter) !== value.marker_after_sha256
      || (markerBefore !== null && !validMcpMarkerBytes(markerBefore, journalAgent, journalServer))
      || (markerAfter !== null && !validMcpMarkerBytes(markerAfter, journalAgent, journalServer))
      || (markerBefore !== null && parseMcpServerMarkerBytes(journalAgent, journalServer, markerBefore)?.config_path !== undefined
        && parseMcpServerMarkerBytes(journalAgent, journalServer, markerBefore)?.config_path !== value.config_path)
      || (markerAfter !== null && parseMcpServerMarkerBytes(journalAgent, journalServer, markerAfter)?.config_path !== value.config_path)
      || (value.action === "install") !== (markerAfter !== null)) {
      throw new Error("journal bytes do not match declared transaction state");
    }
    return {
      journal: value as OwnedMcpPendingJournal,
      configBefore,
      markerBefore,
      markerAfter,
      path,
      bytes,
    };
  } catch (error) {
    throw new Error(`pending ${label} transaction is malformed: ${(error as Error).message}`);
  }
}

function readOwnedMcpPendingLocator(agent: "kilo" | "qwen", serverName: string): ReadOwnedMcpPendingJournal | null {
  const path = canonicalMcpConfigPath(mcpPendingJournalPath(agent, serverName));
  return readOwnedMcpPendingJournalAt(path, { agent, serverName, locatorPath: path });
}

function readOwnedMcpConfigPending(configPath: string): ReadOwnedMcpPendingJournal | null {
  const canonicalPath = canonicalMcpConfigPath(configPath);
  return readOwnedMcpPendingJournalAt(mcpConfigPendingJournalPath(canonicalPath), { configPath: canonicalPath });
}

type OwnedMcpRecovery = "none" | "discarded" | "finalized" | "rolled-back";

function recoverOwnedMcpTransaction(pending: ReadOwnedMcpPendingJournal | null): OwnedMcpRecovery {
  if (!pending) return "none";
  const { journal, configBefore, markerBefore } = pending;

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Read the inner message after 'is malformed:' to identify the exact validation failure.
  2. Fix the specific field or condition named by the inner message (see the underlying errors).
  3. Delete the malformed .pending journals and re-run the MCP server transaction to regenerate valid ones.
  4. If recurring, ensure only one CLI version writes journals and avoid manual edits or third-party rewrites.

Example fix

// before (diagnosing blindly)
kilo mcp recover
// after
node -e 'const j=JSON.parse(require("fs").readFileSync("x.pending")); console.log(j)'  # inspect, fix inner cause, then recover
Defensive patterns

Strategy: try-catch

Try / catch

try { recoverPending(); } catch (e) {
  const m = /is malformed: (.+)$/.exec(e.message);
  if (m) { console.error('Inner cause:', m[1]); /* address inner cause or recreate journal */ }
}

Prevention

When it happens

Trigger: Any of: non-string base64 field, non-canonical base64, non-object JSON, bad schema_version/action/mode/hash fields, or bytes-vs-state mismatch, surfaced while reading the pending journal for an MCP install/uninstall recovery.

Common situations: Same as the inner errors — corrupted or hand-edited journals, version-skewed writers, wrong server/agent pairing — seen through this outer wrapper in logs.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-09-06). Data as JSON: /api/errors/c1ed88c563807d45. Report an issue: GitHub.