{"record":{"id":"1d6ee6e518acfb49","repo":"paperclipai/paperclip","slug":"paperclip-runner-claude-managed-spend-cap-invalid","errorCode":"paperclip_runner_claude_managed_spend_cap_invalid","errorMessage":"The Claude Managed profile requires a positive session spend ceiling.","messagePattern":"The Claude Managed profile requires a positive session spend ceiling\\.","errorType":"error_code","errorClass":"PaperclipRunnerProviderProfileError","httpStatus":null,"severity":"error","filePath":"server/src/services/native-runtime/provider-profile.ts","lineNumber":518,"sourceCode":"      );\n    }\n    const model = profile.model ?? optionalString(stored.defaultModel);\n    const maxSessionListCostUsd = profile.maxSessionListCostUsd\n      ?? stored.defaultMaxListCostCents / 100;\n    if (!model) {\n      throw new PaperclipRunnerProviderProfileError(\n        \"paperclip_runner_claude_managed_model_invalid\",\n        \"The Claude Managed profile requires a model.\",\n      );\n    }\n    if (model !== CLAUDE_MANAGED_QUALIFIED_MODEL) {\n      throw new PaperclipRunnerProviderProfileError(\n        \"paperclip_runner_claude_managed_model_unqualified\",\n        `The Claude Managed profile requires exact model ${CLAUDE_MANAGED_QUALIFIED_MODEL}.`,\n      );\n    }\n    if (!Number.isFinite(maxSessionListCostUsd) || maxSessionListCostUsd <= 0) {\n      throw new PaperclipRunnerProviderProfileError(\n        \"paperclip_runner_claude_managed_spend_cap_invalid\",\n        \"The Claude Managed profile requires a positive session spend ceiling.\",\n      );\n    }\n    return {\n      provider: \"claude_managed\",\n      model,\n      managedProfile: {\n        profileId: stored.id,\n        anthropicAgentId: stored.anthropicAgentId,\n        agentVersion: stored.agentVersion,\n        environmentId: stored.environmentId,\n        betaVersion: CLAUDE_MANAGED_BETA_VERSION,\n      },\n      maxSessionListCostUsd,\n    };\n  }\n  if (profile.provider === \"aws_agentcore\") {","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/native-runtime/provider-profile.ts#L500-L536","documentation":"Every claude_managed run carries a session spend ceiling (maxSessionListCostUsd), taken from the adapter profile override or the stored profile's defaultMaxListCostCents/100. If the resolved value is missing, non-finite, or <= 0, the run is refused. This enforces Paperclip's budget hard-stop invariant on Managed Agents sessions.","triggerScenarios":"provider=claude_managed run where profile.maxSessionListCostUsd is absent/0/negative and stored.defaultMaxListCostCents is 0, negative, null, or non-numeric (making the division NaN).","commonSituations":"A profile seeded with defaultMaxListCostCents left at 0; a run config that explicitly sets maxSessionListCostUsd: 0 intending 'no limit'; a corrupted/migrated profile row where the cents column lost its numeric type.","solutions":["Set maxSessionListCostUsd in the adapter profile config to a positive finite number (e.g. 25).","Set defaultMaxListCostCents on the stored managed profile to a positive integer (e.g. 2500 for $25).","Re-run managed agent setup so the spend ceiling defaults are written correctly.","Fix the DB row if defaultMaxListCostCents is null/0/text after a migration or restore."],"exampleFix":"// before\nproviderProfile: { provider: \"claude_managed\", managedProfileId: \"acme-managed\", model: \"claude-sonnet-5\", maxSessionListCostUsd: 0 }\n// after\nproviderProfile: { provider: \"claude_managed\", managedProfileId: \"acme-managed\", model: \"claude-sonnet-5\", maxSessionListCostUsd: 25 }","handlingStrategy":"validation","validationCode":"const cap = profile.maxSessionListCostUsd ?? (storedProfile.defaultMaxListCostCents ?? 0) / 100;\nif (!(typeof cap === \"number\" && Number.isFinite(cap) && cap > 0)) {\n  throw new Error(\"Configure a positive maxSessionListCostUsd (or defaultMaxListCostCents > 0) before running claude_managed\");\n}","typeGuard":"const hasPositiveCap = (v: unknown): v is number =>\n  typeof v === \"number\" && Number.isFinite(v) && v > 0;","tryCatchPattern":"try {\n  await executeRun(run);\n} catch (e) {\n  if (e instanceof PaperclipRunnerProviderProfileError && e.code === \"paperclip_runner_claude_managed_spend_cap_invalid\") {\n    await managedProfileService.update(profileId, { defaultMaxListCostCents: 2500 }); // $25\n    return executeRun(run);\n  }\n  throw e;\n}","preventionTips":["Set defaultMaxListCostCents to a positive integer at profile creation time","Never encode 'unlimited' as 0 — the schema requires a positive ceiling","Check numeric type of cents columns after DB restores/migrations","Validate spend caps in config linting before deploying adapter configs"],"tags":["configuration","budget","spend-cap","claude-managed"],"backgroundTag":"invalid-spend-cap","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-02T18:44:00.616Z","contentChangedAt":"2026-09-02T18:44:00.616Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}