JuliusBrussee/caveman · error

caveman agent: subagent maxCalls must be a positive integer

Error message

caveman agent: subagent maxCalls must be a positive integer

What it means

The caveman agent `subagent()` helper validates its options before building the tool. `maxCalls` defaults to 1 and must be a positive safe integer (Number.isSafeInteger and > 0), since it caps how many times the subagent tool may be invoked. The library throws this error eagerly at tool-creation time when the caller passes a bad value such as 0, a negative number, a float, or a value exceeding the safe-integer range.

Solutions

  1. Pass a positive integer, e.g. `subagent({ maxCalls: 3 })`, or omit maxCalls to use the default of 1.
  2. If the value comes from config/env, coerce and validate first: `const maxCalls = Number.parseInt(raw, 10)` then check `Number.isSafeInteger(maxCalls) && maxCalls > 0`.
  3. To effectively disable the subagent, do not register it rather than setting maxCalls to 0.

Example fix

// before
const tool = subagent({ name: "researcher", maxCalls: Number(cfg.subagentCalls) });
// after
const maxCalls = Number.parseInt(cfg.subagentCalls, 10);
if (!Number.isSafeInteger(maxCalls) || maxCalls <= 0) throw new Error("bad subagentCalls config");
const tool = subagent({ name: "researcher", maxCalls });
Defensive patterns

Strategy: validation

Validate before calling

function assertMaxCalls(v) {
  if (v === undefined) return 1;
  if (!Number.isSafeInteger(v) || v <= 0) throw new TypeError(`maxCalls must be a positive integer, got ${v}`);
  return v;
}
subagent({ name: "researcher", maxCalls: assertMaxCalls(cfg.maxCalls) });

Type guard

const isPosInt = (v) => typeof v === "number" && Number.isSafeInteger(v) && v > 0;

Try / catch

try {
  const t = subagent({ maxCalls: cfg.maxCalls });
} catch (e) {
  if (e.message.includes("maxCalls must be a positive integer")) {
    console.error(`Config error: subagentCalls='${cfg.maxCalls}' is not a positive integer`);
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `subagent({ maxCalls: 0 })`, `subagent({ maxCalls: -1 })`, `subagent({ maxCalls: 2.5 })`, `subagent({ maxCalls: NaN })`, `subagent({ maxCalls: Infinity })`, or a string coerced from user config instead of a number.

Common situations: Loading maxCalls from an environment variable, CLI flag, or JSON config as a string without parsing; computing maxCalls with arithmetic that yields NaN; copying an example with `maxCalls: 0` to 'disable' the subagent instead of omitting the tool entirely.

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/67949c5796c90908. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/index.ts:175

   */
  maxCostUsd?: number;
  /**
   * This child's wallet in tokens — the denomination sibling of `maxCostUsd`,
   * used by a token-metered run. A token-metered run cannot fund a subagent
   * that declares no token wallet.
   */
  maxTokens?: number;
  maxContextTokens?: number;
}): ToolDefinition {
  const maxInputChars = options.maxInputChars ?? 32_768;
  if (!Number.isSafeInteger(maxInputChars) || maxInputChars <= 0) {
    throw new Error("caveman agent: subagent maxInputChars must be a positive integer");
  }
  const maxCalls = options.maxCalls ?? 1;
  const maxCostUsd = options.maxCostUsd ?? 1;
  const maxContextTokens = options.maxContextTokens ?? 128_000;
  if (!Number.isSafeInteger(maxCalls) || maxCalls <= 0) {
    throw new Error("caveman agent: subagent maxCalls must be a positive integer");
  }
  if (!Number.isFinite(maxCostUsd) || maxCostUsd <= 0) {
    throw new Error("caveman agent: subagent maxCostUsd must be positive");
  }
  if (options.maxTokens !== undefined &&
      (!Number.isSafeInteger(options.maxTokens) || options.maxTokens <= 0)) {
    throw new Error("caveman agent: subagent maxTokens must be a positive integer");
  }
  if (!Number.isSafeInteger(maxContextTokens) || maxContextTokens <= 0) {
    throw new Error("caveman agent: subagent maxContextTokens must be a positive integer");
  }
  return tool({
    name: options.name,
    description: options.description,
    input: schema.object({ task: schema.string() }),
    effect: "read",
    result: "auto",
    ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),

View on GitHub (pinned to 3ee70a1026)