{"record":{"id":"35a4fe6e5b1ffdea","repo":"paperclipai/paperclip","slug":"goal-token-budget-unsupported","errorCode":"goal_token_budget_unsupported","errorMessage":"goal_token_budget_unsupported: This agent session does not support goal token budgets.","messagePattern":"goal_token_budget_unsupported: This agent session does not support goal token budgets\\.","errorType":"error_code","errorClass":"RunnerGoalActionError","httpStatus":null,"severity":"warning","filePath":"server/src/services/runner-goals.ts","lineNumber":431,"sourceCode":"      if (session.goalRevision !== request.expectedRevision) {\n        throw new RunnerGoalConflictError(\"stale_revision\", currentProjection);\n      }\n      const capability = storedCapability(session, fallbackCapability);\n      const requiredCapabilityAction = request.action === \"pause\"\n        ? \"pause\"\n        : request.action === \"resume\"\n          ? \"resume\"\n          : request.action === \"clear\"\n            ? \"clear\"\n            : \"set\";\n      if (capability.availability !== \"available\" || !capability.actions.includes(requiredCapabilityAction)) {\n        throw new RunnerGoalActionError(\n          capability.reasonCode ?? \"goal_action_unsupported\",\n          capability.reason ?? `${request.action} is unsupported by this agent session.`,\n        );\n      }\n      if (request.tokenBudget != null && !capability.tokenBudgetControl) {\n        throw new RunnerGoalActionError(\n          \"goal_token_budget_unsupported\",\n          \"This agent session does not support goal token budgets.\",\n        );\n      }\n      if (request.action === \"create\" && currentGoal && currentGoal.status !== \"complete\") {\n        throw new RunnerGoalConflictError(\"replacement_required\", currentProjection);\n      }\n      if ([\"edit\", \"replace\", \"pause\", \"resume\", \"clear\"].includes(request.action) && !currentGoal) {\n        throw new RunnerGoalActionError(\"goal_not_found\", \"There is no current session goal.\");\n      }\n\n      const nextRevision = session.goalRevision + 1;\n      const desiredState = request.action === \"pause\"\n        ? \"paused\"\n        : request.action === \"clear\"\n          ? null\n          : \"active\";\n      await tx.update(agentTaskSessions).set({","sourceCodeStart":413,"sourceCodeEnd":449,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/runner-goals.ts#L413-L449","documentation":"`act` rejects goal actions carrying a `tokenBudget` when the session's capability lacks `tokenBudgetControl`, throwing code `goal_token_budget_unsupported`. Goal-level token budgets are an optional adapter capability; requesting one on a session that can't enforce it is a hard error.","triggerScenarios":"Including `tokenBudget` in RunnerGoalActionRequest for an agent/adapter that does not advertise `capability.tokenBudgetControl`; blindly forwarding a tokenBudget field from generic goal tooling.","commonSituations":"Generic goal-management UI always sends tokenBudget; migrating workflows between adapters with differing budget support; adapter capability probe didn't detect budget control so the field is unsupported.","solutions":["Omit `tokenBudget` from the request when `capability.tokenBudgetControl` is falsy","Check the projection before sending: `if (proj.capability.tokenBudgetControl)` gate the field","Enforce budgets out-of-band (board-level budget auto-pause) for adapters without goal budget support","Upgrade to an adapter that supports token budget control if budgets are required"],"exampleFix":"// before\nawait act(companyId, issueId, { agentId, action: 'set', goal, tokenBudget: 5000 });\n// after\nconst proj = await projection(companyId, issueId, agentId);\nawait act(companyId, issueId, { agentId, action: 'set', goal,\n  ...(proj.capability.tokenBudgetControl ? { tokenBudget: 5000 } : {}) });","handlingStrategy":"validation","validationCode":"const proj = await runnerGoals.projection(companyId, issueId, agentId);\nif (tokenBudget != null && !proj.capability.tokenBudgetControl) {\n  delete req.tokenBudget; // or reject at the call site\n}","typeGuard":"function supportsTokenBudget(proj) {\n  return proj?.capability?.tokenBudgetControl === true;\n}","tryCatchPattern":"try {\n  await runnerGoals.act(companyId, issueId, req);\n} catch (e) {\n  if (e instanceof RunnerGoalActionError && e.code === 'goal_token_budget_unsupported') {\n    const { tokenBudget, ...rest } = req;\n    return await runnerGoals.act(companyId, issueId, rest); // retry without budget\n  }\n  throw e;\n}","preventionTips":["Conditionally include tokenBudget only when capability.tokenBudgetControl is true","Never blanket-forward tokenBudget from generic tooling","Offer budget UI only for budget-capable adapters","Use board-level budget controls as the fallback"],"tags":["capability","token-budget","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}