JuliusBrussee/caveman · error · Error
caveman agent: subagent maxTokens must be a positive integer
Error message
caveman agent: subagent maxTokens must be a positive integer
What it means
Thrown by the subagent tool factory when options.maxTokens is present but not a safe positive integer. maxTokens optionally caps the subagent model's output tokens; because it is optional, passing undefined skips the check, but any supplied value must be a whole number >= 1 (NaN, 0, negatives, floats, and numeric strings all throw).
Source
Thrown at packages/agent/src/index.ts:182
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 }),
runtime: {
kind: "subagent",
definition: options.agent,
maxInputChars,
maxCalls,
maxCostUsd,
...(options.maxTokens === undefined ? {} : { maxTokens: options.maxTokens }),View on GitHub (pinned to 27d5a3981a)
Solutions
- Pass a positive safe integer, e.g. maxTokens: 8192
- If you do not need an output cap, omit the option entirely (undefined is accepted)
- Normalize optional config: maxTokens: cfg.maxTokens ?? undefined after checking it is a safe integer > 0
- Clamp floats: Math.max(1, Math.round(cfg.maxTokens))
Example fix
// before
subagentTool({ agent, name: "worker", maxTokens: cfg.max_tokens ?? 0 });
// after
subagentTool({
agent,
name: "worker",
...(Number.isSafeInteger(cfg.max_tokens) && cfg.max_tokens > 0
? { maxTokens: cfg.max_tokens }
: {}),
}); Defensive patterns
Strategy: validation
Validate before calling
if (cfg.maxTokens !== undefined &&
(!Number.isSafeInteger(cfg.maxTokens) || cfg.maxTokens <= 0)) {
throw new Error(`maxTokens must be a positive integer when provided, got ${cfg.maxTokens}`);
}
subagentTool({ agent, name: "worker", ...(cfg.maxTokens === undefined ? {} : { maxTokens: cfg.maxTokens }) }); Type guard
const isOptionalPositiveInt = (v: unknown): v is number | undefined => v === undefined || (Number.isSafeInteger(v) && v > 0);
Prevention
- Keep maxTokens optional in your own config types so absent means omitted, not 0
- Map provider sentinels (-1 for default) to undefined before passing through
- Round any computed token budget: Math.max(1, Math.round(v))
When it happens
Trigger: Explicitly passing maxTokens: 0, maxTokens: -1, maxTokens: 4096.5, maxTokens: NaN, or maxTokens: "4096". Unlike maxCalls/maxContextTokens there is no default — the error only fires when the option is defined and invalid.
Common situations: Forwarding a model-config object where maxTokens is optional and sometimes null/0, converting a provider's token limit (some providers accept -1 for 'default', this library does not), or typo'ing a numeric string.
Related errors
- caveman agent: subagent maxInputChars must be a positive int
- caveman agent: subagent maxCalls must be a positive integer
- caveman agent: subagent maxCostUsd must be positive
- caveman agent: subagent maxContextTokens must be a positive
- cave_breaker_threshold_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/34ad719f94032c51.
Report an issue: GitHub.