paperclipai/paperclip · error
ACPX session goal action ${action} is unavailable
Error message
ACPX session goal action ${action} is unavailable What it means
controlGoal() on the AcpxRuntimePort validates the requested goal action against the session's declared goal capability before sending anything to the ACPX runtime. If no capability was negotiated for the session, or the capability exists but does not list the requested action (e.g. 'set', 'pause', 'resume', 'clear'), the adapter throws this error instead of dispatching an extension request the backend would reject. It is a capability gate ensuring only actions the Codex runtime advertised are attempted.
Source
Thrown at packages/paperclip-runner/src/drivers/acpx/codex-runtime-adapter.ts:1103
return structuredClone(identity);
},
async getStatus() {
return await persistedRuntimeStatus(sessionStore, handle, identity);
},
goalCapability() {
return goalState.capability === null
? null
: structuredClone(goalState.capability);
},
goalSnapshot() {
return goalState.snapshot === null
? null
: structuredClone(goalState.snapshot);
},
async controlGoal(action, objective) {
const capability = goalState.capability;
if (!capability || !capability.actions.includes(action)) {
throw new Error(`ACPX session goal action ${action} is unavailable`);
}
if (!runtime.requestExtension) {
throw new Error("ACPX runtime does not expose extension requests");
}
const revisionBeforeControl = goalState.revision;
await runtime.requestExtension({
handle,
method: capability.controlMethod,
params: {
sessionId: identity.agentSessionId,
action,
...(action === "set" ? { objective } : {}),
},
sessionMode: "persistent",
});
const shouldRepairMissingSetSnapshot =
action === "set" &&
Boolean(objective?.trim()) &&View on GitHub (pinned to 01ad858492)
Solutions
- Check port.goalCapability() before calling controlGoal and only offer/execute actions present in capability.actions.
- If the capability is null, do not attempt goal control on this session; upgrade the ACPX/Codex runtime to a version that advertises goal support.
- Fix the caller's action identifier (exact match against capability.actions) and retry with a supported action.
- Catch the error and degrade gracefully (skip goal control UI for sessions without the capability).
Example fix
// before
await port.controlGoal("pause", undefined); // throws if 'pause' unsupported
// after
const capability = port.goalCapability();
if (capability?.actions.includes("pause")) {
await port.controlGoal("pause", undefined);
} else {
throw new Error("goal pause not supported by this session");
} Defensive patterns
Strategy: validation
Validate before calling
const capability = port.goalCapability();
if (!capability || !capability.actions.includes(action)) {
throw new Error(`action ${action} not offered by this session`);
} Type guard
function canControlGoal(port, action) {
const capability = port.goalCapability();
return Array.isArray(capability?.actions) && capability.actions.includes(action);
} Try / catch
try {
await port.controlGoal(action, objective);
} catch (e) {
if (String(e.message).startsWith("ACPX session goal action")) {
disableGoalControlUi();
} else throw e;
} Prevention
- Always read goalCapability() before exposing goal actions in UI or automation.
- Treat capability.actions as the single source of truth for allowed actions.
- Handle capability === null as 'goal control unsupported' in all callers.
When it happens
Trigger: Calling port.controlGoal(action, objective) where goalState.capability is null (the runtime never advertised goal support for this session) or capability.actions does not include the given action string.
Common situations: Issuing a goal 'pause'/'resume' against a Codex runtime version or session mode that only supports 'set'/'clear'; calling controlGoal on a session spawned without goal capability negotiation; a typo'd action name; reusing a goal-control helper across runtimes where only some expose goal actions.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- ACPX runtime does not expose session goal controls
- Sandbox driver does not support duplex channels for this lea
- Environment driver "${driver.driver}" does not support duple
- Native ACPX backend for pi is unavailable until descriptor-c
- The Pi ACPX profile is not available
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/39fb834d8ef18310.
Report an issue: GitHub.