JuliusBrussee/caveman · error · Error

cave_subagent_concurrency_limit_invalid

cave_subagent_concurrency_limit_invalid

Error message

cave_subagent_concurrency_limit_invalid

What it means

RunOptions.maxConcurrentSubagents caps simultaneously active descendant subagents. streamAgentInternal validates it at run start: it must be a safe integer > 0 and at most ABSOLUTE_SUBAGENT_INVOCATION_LIMIT (1,000,000). Invalid values throw before any execution begins.

Solutions

  1. Pass a positive safe integer between 1 and 1,000,000 for maxConcurrentSubagents.
  2. Validate/clamp the value before the call: Math.max(1, Math.floor(v)).
  3. Omit the option to leave concurrency uncapped by this control.

Example fix

// before
runAgent(def, input, { maxConcurrentSubagents: opts.parallel });
// after
const p = Math.floor(Number(opts.parallel));
runAgent(def, input, Number.isSafeInteger(p) && p > 0
  ? { maxConcurrentSubagents: p }
  : {});
Defensive patterns

Strategy: validation

Validate before calling

function isValidConcurrencyLimit(v) {
  return v === undefined || (Number.isSafeInteger(v) && v > 0 && v <= 1_000_000);
}

Type guard

function hasValidMaxConcurrentSubagents(o) {
  return o.maxConcurrentSubagents === undefined ||
    (Number.isSafeInteger(o.maxConcurrentSubagents) && o.maxConcurrentSubagents > 0);
}

Try / catch

try {
  await runAgent(def, input, opts);
} catch (err) {
  if (err.message === "cave_subagent_concurrency_limit_invalid") {
    opts.maxConcurrentSubagents = Math.max(1, Math.floor(Number(opts.maxConcurrentSubagents)) || 1);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling runAgent/streamAgent with options.maxConcurrentSubagents set to 0, a negative number, a non-integer, NaN/Infinity, or a value above 1,000,000.

Common situations: Env/JSON-derived config parsed as float or string; a "no concurrency" intent expressed as 0 instead of omitting the option; formula-generated caps producing 0 or fractional values.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/072ed9e10e3ec079. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/runtime.ts:1067

    },
  } as AsyncGenerator<CavemanRunEvent>;
}

async function* streamAgentInternal(
  definition: AgentDefinition,
  input: string,
  options: InternalRunOptions,
  executionContext: InternalExecutionContext,
): AsyncGenerator<CavemanRunEvent> {
  if (options.maxSubagentInvocations !== undefined &&
      (!Number.isSafeInteger(options.maxSubagentInvocations) || options.maxSubagentInvocations <= 0 ||
        options.maxSubagentInvocations > ABSOLUTE_SUBAGENT_INVOCATION_LIMIT)) {
    throw new Error("cave_subagent_invocation_limit_invalid");
  }
  if (options.maxConcurrentSubagents !== undefined &&
      (!Number.isSafeInteger(options.maxConcurrentSubagents) || options.maxConcurrentSubagents <= 0 ||
        options.maxConcurrentSubagents > ABSOLUTE_SUBAGENT_INVOCATION_LIMIT)) {
    throw new Error("cave_subagent_concurrency_limit_invalid");
  }
  if (options.lockedBuild !== undefined && options.candidatePlan !== undefined) {
    throw new Error("cave_execution_authorization_ambiguous");
  }
  // Budget shape is settled before anything else happens: an ambiguous or
  // unbounded budget must fail at run() start, not after the first dollar.
  // maxCostUsd and budget are two different contracts for the same money —
  // one terminates with an error, the other returns a planned partial result —
  // so carrying both would leave the run's own stop semantics undecided.
  if (options.budget !== undefined && options.maxCostUsd !== undefined) {
    throw new Error("cave_budget_conflicting_cap");
  }
  const budgetMeter = executionContext.budgetMeter ?? (options.budget === undefined
    ? undefined
    : new BudgetMeter(normalizeRunBudget(options.budget)));
  if (options.deadlineMs !== undefined &&
      (!Number.isSafeInteger(options.deadlineMs) || options.deadlineMs <= 0)) {
    throw new Error("cave_run_deadline_invalid");

View on GitHub (pinned to 3ee70a1026)