{"record":{"id":"e5205ab37e2452e0","repo":"JuliusBrussee/caveman","slug":"cave-run-deadline-invalid","errorCode":"cave_run_deadline_invalid","errorMessage":"cave_run_deadline_invalid","messagePattern":"cave_run_deadline_invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/runtime.ts","lineNumber":1085,"sourceCode":"    throw new Error(\"cave_subagent_concurrency_limit_invalid\");\n  }\n  if (options.lockedBuild !== undefined && options.candidatePlan !== undefined) {\n    throw new Error(\"cave_execution_authorization_ambiguous\");\n  }\n  // Budget shape is settled before anything else happens: an ambiguous or\n  // unbounded budget must fail at run() start, not after the first dollar.\n  // maxCostUsd and budget are two different contracts for the same money —\n  // one terminates with an error, the other returns a planned partial result —\n  // so carrying both would leave the run's own stop semantics undecided.\n  if (options.budget !== undefined && options.maxCostUsd !== undefined) {\n    throw new Error(\"cave_budget_conflicting_cap\");\n  }\n  const budgetMeter = executionContext.budgetMeter ?? (options.budget === undefined\n    ? undefined\n    : new BudgetMeter(normalizeRunBudget(options.budget)));\n  if (options.deadlineMs !== undefined &&\n      (!Number.isSafeInteger(options.deadlineMs) || options.deadlineMs <= 0)) {\n    throw new Error(\"cave_run_deadline_invalid\");\n  }\n  if (options.maxSubagentDepth !== undefined &&\n      (!Number.isSafeInteger(options.maxSubagentDepth) || options.maxSubagentDepth <= 0 ||\n        options.maxSubagentDepth > ABSOLUTE_SUBAGENT_DEPTH_LIMIT)) {\n    throw new Error(\"cave_subagent_depth_limit_invalid\");\n  }\n  const deadlineAt = executionContext.deadlineAt ?? (options.deadlineMs === undefined\n    ? undefined\n    : performance.now() + options.deadlineMs);\n  // A controller with nothing to release would be a silent no-op at the\n  // checkpoint that expected it to matter.\n  if (options.budgetController !== undefined && budgetMeter === undefined) {\n    throw new Error(\"cave_budget_controller_without_budget\");\n  }\n  const breakers = options.breakers === undefined\n    ? undefined\n    : new BreakerState(normalizeRunBreakers(options.breakers, budgetMeter !== undefined));\n  const efficiencyPlan = options.lockedBuild?.selected_plan ?? options.candidatePlan;","sourceCodeStart":1067,"sourceCodeEnd":1103,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/runtime.ts#L1067-L1103","documentation":"Thrown at run start when RunOptions.deadlineMs is present but not a safe integer greater than zero. The deadline stops the run at the same between-call checkpoints as the budget; a fractional, zero, negative, or non-finite deadline is a malformed value and is rejected before execution rather than treated as 'no deadline'.","triggerScenarios":"Passing deadlineMs: 0, a negative number, a float like 1500.5, NaN, or Infinity. Note executionContext.deadlineAt can also carry an inherited deadline, but the option itself must still be a positive safe integer when supplied.","commonSituations":"Computing a deadline from a remaining-time calculation that has already hit zero; passing seconds instead of milliseconds as a float; reading an unset env/config value that becomes NaN.","solutions":["Pass a positive integer number of milliseconds, e.g. deadlineMs: 60_000, or omit it for no deadline","If the computed remaining time is already <= 0, skip starting the run rather than passing 0","Round computed values: Math.max(1, Math.floor(remainingMs))"],"exampleFix":"// before\nawait agent.run(input, { deadlineMs: endAt - Date.now() }); // 0 or negative when overdue\n\n// after\nconst remaining = endAt - Date.now();\nif (remaining <= 0) throw new Error(\"deadline already passed\");\nawait agent.run(input, { deadlineMs: Math.floor(remaining) });","handlingStrategy":"validation","validationCode":"const remaining = endAt - Date.now();\nconst opts = Number.isSafeInteger(remaining) && remaining > 0\n  ? { deadlineMs: remaining }\n  : {}; // skip the run if remaining <= 0","typeGuard":"const isValidDeadline = (v: unknown): v is number =>\n  typeof v === \"number\" && Number.isSafeInteger(v) && v > 0;","tryCatchPattern":null,"preventionTips":["Floor computed deadlines and reject non-positive remainders before calling run","Remember the unit is milliseconds","Do not pass 0 hoping it means 'immediate stop' — it is invalid"],"tags":["deadline","validation","run-options"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}