{"record":{"id":"f49d2cbe61a3d643","repo":"can1357/oh-my-pi","slug":"checkpoint-already-completed-continue-from-the-re","errorCode":null,"errorMessage":"Checkpoint already completed; continue from the retained rewind report instead of calling rewind again.","messagePattern":"Checkpoint already completed; continue from the retained rewind report instead of calling rewind again\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/checkpoint.ts","lineNumber":117,"sourceCode":"\n\tconstructor(private readonly session: ToolSession) {\n\t\tthis.description = prompt.render(rewindDescription);\n\t}\n\n\tstatic createIf(session: ToolSession): RewindTool | null {\n\t\treturn new RewindTool(session);\n\t}\n\n\tasync execute(\n\t\t_toolCallId: string,\n\t\tparams: RewindParams,\n\t\t_signal?: AbortSignal,\n\t\t_onUpdate?: AgentToolUpdateCallback<RewindToolDetails>,\n\t\t_context?: AgentToolContext,\n\t): Promise<AgentToolResult<RewindToolDetails>> {\n\t\tif (!this.session.getCheckpointState?.()) {\n\t\t\tif (this.session.getLastCompletedRewind?.()) {\n\t\t\t\tthrow new ToolError(\n\t\t\t\t\t\"Checkpoint already completed; continue from the retained rewind report instead of calling rewind again.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new ToolError(\"No active checkpoint. Create a checkpoint before calling rewind.\");\n\t\t}\n\t\tconst report = params.report.trim();\n\t\tif (report.length === 0) {\n\t\t\tthrow new ToolError(\"Report cannot be empty.\");\n\t\t}\n\t\treturn toolResult<RewindToolDetails>({ report, rewound: true })\n\t\t\t.text([\"Rewind requested.\", \"Report captured for context replacement.\"].join(\"\\n\"))\n\t\t\t.done();\n\t}\n}\n","sourceCodeStart":99,"sourceCodeEnd":132,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/checkpoint.ts#L99-L132","documentation":"The checkpoint rewind tool refuses to run a second rewind because a rewind has already been completed in this session: the checkpoint state was consumed and cleared, and only the final rewind report is retained. The library throws this instead of silently re-rewinding, because rewinding twice could clobber work done after the first rewind. The agent should use the already-captured rewind report (e.g. for context replacement) rather than invoking the tool again.","triggerScenarios":"Calling the rewind tool's execute() when session.getCheckpointState() returns falsy AND session.getLastCompletedRewind() returns truthy — i.e. a rewind already finished earlier in the same session and the tool is invoked again.","commonSituations":"An LLM agent retries the rewind tool call because it didn't register that the first call succeeded; a scripted workflow calls rewind twice expecting idempotence; session state was restored mid-run losing the live checkpoint but retaining the completed-rewind marker.","solutions":["Do not call the rewind tool again; read the report from session.getLastCompletedRewind() and continue from it.","If a real second rewind is needed, create a new checkpoint first, then call rewind.","Clear the completed-rewind marker (or start a fresh session) before issuing a new rewind request."],"exampleFix":"// before (agent tool loop)\nawait session.tools.rewind({ report: secondReport });\n\n// after\nconst previous = session.getLastCompletedRewind?.();\nif (previous && !session.getCheckpointState?.()) {\n  usePreviousReport(previous.report); // don't call rewind again\n} else {\n  await session.tools.rewind({ report: secondReport });\n}","handlingStrategy":"validation","validationCode":"if (!session.getCheckpointState?.() && session.getLastCompletedRewind?.()) {\n  // rewind already done — use the retained report, don't call rewind again\n}","typeGuard":null,"tryCatchPattern":"try {\n  await rewindTool.execute(params, ...);\n} catch (err) {\n  if (err instanceof ToolError && /already completed/.test(err.message)) {\n    const report = session.getLastCompletedRewind?.()?.report;\n    // continue from retained report\n  } else throw err;\n}","preventionTips":["Track rewind completion in the agent's tool-call loop so repeat calls are suppressed.","Check session.getCheckpointState() before scheduling any rewind.","In prompts, instruct the model that rewind is single-shot per checkpoint."],"tags":["checkpoint","rewind","tool-error","state"],"backgroundTag":"checkpoint-already-completed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}