paperclipai/paperclip · error · RunnerGoalActionError
runner_goal_live_controller_unavailable
runner_goal_live_controller_unavailable
Error message
runner_goal_live_controller_unavailable: The live agent goal controller is unavailable; the run was not interrupted.
What it means
settleLiveRunnerGoalBeforeInterrupt throws RunnerGoalActionError(runner_goal_live_controller_unavailable) when it decided a pause/clear action is required, but neither the live adapter control dispatch nor the queued PRP command returned a completion promise. The stop command could not be handed to any controller, so the run was definitively NOT interrupted — the failure is reported instead of leaving an unknown state.
Source
Thrown at server/src/services/runner-goals.ts:983
"The live agent goal cannot be stopped safely.",
);
}
const requestId = `interrupt_${randomUUID()}`;
const adapterControl = dispatchLiveRunnerGoalControl(binding, { requestId, action });
const nativeControl = adapterControl
? null
: queueLiveRunnerPrpCommand({
...binding,
type: action === "pause" ? "session.goal.set" : "session.goal.clear",
payload: action === "pause"
? { requestId, status: "paused" }
: { requestId },
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
- Verify the agent adapter session is still alive and registered with dispatchLiveRunnerGoalControl before calling the interrupt path.
- Check logs for controller deregistration (process exit, reconnect) around the failure time and re-attach/restart the session.
- Ensure the PRP offline command queue (queueLiveRunnerPrpCommand) is accepting commands for this session; fix queue unavailability.
- Retry settleLiveRunnerGoalBeforeInterrupt once the session controller is re-established; the run was not interrupted so no cleanup is needed.
Example fix
// before: call stop immediately after process restart await settleLiveRunnerGoalBeforeInterrupt(db, binding); // after: ensure a controller exists first const controller = getLiveController(binding); if (!controller) await restartAgentSession(binding); // re-register live controller await settleLiveRunnerGoalBeforeInterrupt(db, binding);
Defensive patterns
Strategy: fallback
When it happens
Trigger: dispatchLiveRunnerGoalControl(binding, {requestId, action}) returns null (no live adapter controller attached to the session) AND queueLiveRunnerPrpCommand(...) also returns null (offline/queued command path unavailable), so adapterControl?.completion ?? nativeControl?.completion is null.
Common situations: Interrupting a run after the adapter process/connection died so no live controller is registered; a service restart dropped the in-flight controller registration; the PRP command queue rejects or drops the command (e.g. session no longer tracked); calling the stop path for a session that was never bound to a live controller.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- runner_goal_stop_unsupported
- Adapter declares unsupported UI parser contract version — sk
- UI parser path escapes package directory — skipping
- ${prefix}: the capability must be an object.
- ${prefix}: "panelMode" must be one of ${ADAPTER_LOGIN_PANEL_
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/901ed07686b4e2bc.
Report an issue: GitHub.