paperclipai/paperclip · error · RunnerGoalActionError
runner_goal_stop_unconfirmed
runner_goal_stop_unconfirmed
Error message
runner_goal_stop_unconfirmed: The provider did not confirm that the live agent goal stopped.
What it means
settleLiveRunnerGoalBeforeInterrupt polls the goal projection every 25ms for up to 5 seconds after issuing a pause or clear to the live provider. If the projection never shows status "paused" (for pause) or a null goal (for clear) within that window, it throws RunnerGoalActionError(runner_goal_stop_unconfirmed): the command was delivered but the provider never confirmed the stop, so the caller must not interrupt the process.
Source
Thrown at server/src/services/runner-goals.ts:997
commandId: `goal_${requestId}`,
});
const completion = adapterControl?.completion ?? nativeControl?.completion ?? null;
if (!completion) {
throw new RunnerGoalActionError(
"runner_goal_live_controller_unavailable",
"The live agent goal controller is unavailable; the run was not interrupted.",
);
}
await completion;
const deadline = Date.now() + 5_000;
while (Date.now() < deadline) {
const observed = await goals.projection(binding.companyId, binding.issueId, binding.agentId);
if (action === "pause" && observed?.goal?.status === "paused") return "paused";
if (action === "clear" && observed?.goal === null) return "cleared";
await new Promise<void>((resolve) => setTimeout(resolve, 25));
}
throw new RunnerGoalActionError(
"runner_goal_stop_unconfirmed",
"The provider did not confirm that the live agent goal stopped.",
);
}
View on GitHub (pinned to 01ad858492)
Solutions
- Retry settleLiveRunnerGoalBeforeInterrupt after a short wait — the provider may simply have been slower than the 5s deadline; check the projection first, as the goal may now be paused/cleared.
- Inspect the provider/adapter logs to see whether the pause/clear command was actually processed; fix the provider handler if it acks without applying.
- Verify the goal event path (applyRunnerGoalPrpEvent / projection) is applying state changes for this session; a stuck projection makes confirmation impossible.
- If the goal is genuinely stuck active, stop it through the provider's own UI/CLI, then re-run the interrupt flow once the projection shows paused or cleared.
Example fix
// before
try { await settleLiveRunnerGoalBeforeInterrupt(db, binding); } catch (e) { interruptProcess(); }
// after
try {
await settleLiveRunnerGoalBeforeInterrupt(db, binding);
} catch (e) {
if (e?.code === "runner_goal_stop_unconfirmed") {
const p = await runnerGoalService(db).projection(binding.companyId, binding.issueId, binding.agentId);
if (p?.goal?.status === "paused" || p?.goal === null) return; // late confirmation; now safe
}
throw e; // still unconfirmed — do NOT interrupt
} Defensive patterns
Strategy: retry
When it happens
Trigger: Calling settleLiveRunnerGoalBeforeInterrupt() where the adapter/PRP completion resolves but goals.projection() still returns an active goal after 5s: the provider accepted the pause/clear command yet never applied it, or applied it slower than the 5s deadline, or the projection read path diverges from the applied state.
Common situations: Slow or overloaded provider taking longer than 5 seconds to honor pause/clear; a provider that acks control commands without acting on them; projection staleness (event not yet applied via applyRunnerGoalPrpEvent); long-running non-interruptible work in the agent that defers the pause.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- provider turn ended with status ${turn.status}
- runner_prp_command_timeout:${command.commandId}
- Failed to stop Daytona sandbox during lease release: ${forma
- [opencode-local] Remote model availability probe for "${mode
- ${prefix}: "timeoutPolicy" must be one of ${ADAPTER_LOGIN_TI
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/0e75f7663e9e68ee.
Report an issue: GitHub.