paperclipai/paperclip · error

The negotiated ACP goal extension does not support token bud

Error message

The negotiated ACP goal extension does not support token budget control

What it means

The ACP goal extension negotiated with the runtime only supports objective/status management, not per-session token budget control. When a client sends the session.goal.set command with a tokenBudget field, the sidecar rejects it outright because the capability is unavailable in this negotiation, rather than silently ignoring the budget.

Source

Thrown at packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts:453

      ),
      status: sanitizeRuntimeStatus(
        await readSidecarHostStatusWithin(activeHost),
      ),
      runId,
      turnId,
      sequence,
      pendingToolCount: tools.size,
      pendingInputCount: inputs.size,
    };
  }
  if (request.command === "session.goal.get") {
    const activeHost = requireHost();
    return observedGoalProjection(activeHost.goalCapability(), activeHost.goalSnapshot(), turnId !== null);
  }
  if (request.command === "session.goal.set") {
    const activeHost = requireHost();
    if (Object.prototype.hasOwnProperty.call(request.params, "tokenBudget")) {
      throw new Error("The negotiated ACP goal extension does not support token budget control");
    }
    const objective = text(request.params.objective).trim();
    const status = text(request.params.status).trim();
    const action = objective
      ? "set"
      : status === "paused"
        ? "pause"
        : status === "active"
          ? "resume"
          : null;
    if (!action) throw new Error("session.goal.set requires an objective or active/paused status");
    const goal = await activeHost.controlGoal(action, objective || undefined);
    return observedGoalProjection(activeHost.goalCapability(), goal, turnId !== null);
  }
  if (request.command === "session.goal.clear") {
    const activeHost = requireHost();
    await activeHost.controlGoal("clear");
    return observedGoalProjection(activeHost.goalCapability(), null, turnId !== null);

View on GitHub (pinned to 01ad858492)

Solutions

  1. Remove the tokenBudget property from the session.goal.set params
  2. Gate token budget handling behind the negotiated goal capability before sending the command
  3. Update to a runtime build whose ACP goal extension supports token budget control

Example fix

// before
host.dispatch({ command: 'session.goal.set', params: { objective: 'ship', tokenBudget: 5000 } });
// after
host.dispatch({ command: 'session.goal.set', params: { objective: 'ship' } });
Defensive patterns

Strategy: validation

Validate before calling

function canSetGoalWithBudget(params) { return params && !('tokenBudget' in params); }
if (!canSetGoalWithBudget(params)) delete params.tokenBudget;

Type guard

function isBudgetFreeGoalParams(p: unknown): p is { objective?: string; status?: string } {
  return typeof p === 'object' && p !== null && !('tokenBudget' in p);
}

Try / catch

try { await host.dispatch({ command: 'session.goal.set', params }); }
catch (e) { if (String(e.message).includes('token budget control')) { const { tokenBudget, ...rest } = params; await host.dispatch({ command: 'session.goal.set', params: rest }); } else throw e; }

Prevention

When it happens

Trigger: Sending a dispatch request with command 'session.goal.set' whose params object contains a 'tokenBudget' property (checked via hasOwnProperty, so even null/undefined values trigger it).

Common situations: A caller upgraded from a runtime build that supported token budgets, or a client library always includes tokenBudget in goal-set params; generic orchestration code reusing one params shape across goal operations.

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


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