paperclipai/paperclip · error

PRP command ${type} omitted its durable result

Error message

PRP command ${type} omitted its durable result

What it means

Thrown from `#commandResult` after `#waitCommand` resolves but the stored command is not in `status === "completed"` with the expected `type`. The PRP command lifecycle promises a durable result record; if the command record is missing, typed differently, or never reached `completed`, the transport treats the protocol contract as broken and throws rather than reading a bogus `command.result`.

Source

Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:5460

    } else {
      core.queueCommand(type, payload, commandId, true);
    }
    await this.#waitCommand(type, commandId);
  }

  async #commandResult(
    type: string,
    payload: Record<string, unknown>,
    deadline?: number,
  ): Promise<Record<string, unknown>> {
    const core = this.#core;
    if (core === null) throw new Error("PRP provider thread is not started");
    const commandId = `command_lab_${randomUUID().replaceAll("-", "")}`;
    core.queueCommand(type, payload, commandId, true);
    await this.#waitCommand(type, commandId, deadline);
    const command = core.getCommand(commandId);
    if (command?.status !== "completed" || command.type !== type) {
      throw new Error(`PRP command ${type} omitted its durable result`);
    }
    const result = record(record(command.result).result);
    const completion = this.#pendingWarmRecoveryCompletion;
    if (completion && type === "session.snapshot") {
      const expectation = this.#checkpointProviderIdentityExpectation;
      const providerIdentity = resolveRunnerdSessionIdentity(result);
      if (
        command.type !== "session.snapshot" ||
        core.store.state.warmTransition !== undefined ||
        !recoveryIdentityMatches(
          core.store.state.identity,
          completion.identity,
        ) ||
        core.store.state.completedWarmTransition?.receipt.transitionId !==
          completion.transitionId ||
        expectation === null ||
        providerIdentity.threadId !== expectation.driverSessionId ||
        providerIdentity.sessionId !== expectation.providerSessionId ||

View on GitHub (pinned to 01ad858492)

Solutions

  1. Inspect runnerd logs around the command ID to see whether the durable result was persisted; restart runnerd if it crashed mid-command.
  2. Retry the command — a fresh commandId and queueCommand round-trip usually re-establishes the durable result.
  3. Verify transport and runnerd protocol versions agree on the command `type` string.
  4. If the wait helper can return on non-completion, tighten `#waitCommand` so it only resolves when the command is completed.

Example fix

// before
await this.#waitCommand(type, commandId, deadline);
const command = core.getCommand(commandId);
// after
const completed = await this.#waitCommand(type, commandId, deadline).catch(() => null);
if (!completed) throw new Error(`PRP command ${type} omitted its durable result`);
const command = core.getCommand(commandId);
Defensive patterns

Strategy: retry

Validate before calling

const cmd = core.getCommand(commandId);
if (!cmd || cmd.type !== type) throw new Error(`command ${commandId} missing or mistyped`);

Type guard

function isCompletedCommand(c, type) {
  return !!c && c.status === "completed" && c.type === type;
}

Try / catch

try {
  await this.#commandResult(type, payload, deadline);
} catch (err) {
  if (err.message.includes("omitted its durable result")) {
    await this.#commandResult(type, payload, deadline); // one retry with fresh commandId
  } else throw err;
}

Prevention

When it happens

Trigger: `core.queueCommand(type, payload, commandId, true)` followed by `#waitCommand`, but `core.getCommand(commandId)` returns undefined (command purged/reset), a different `type`, or a non-completed status that `#waitCommand` did not reject on (e.g. wait resolved by deadline/other path).

Common situations: runnerd crashed mid-command so the durable result was never written; command store reset between queue and get; protocol mismatch where the completion arrives under a different command type; a bug letting `#waitCommand` return without completion.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/eee10063f790fdf7. Report an issue: GitHub.