JuliusBrussee/caveman · error · Error

caveman agent: output maxTokens must be a positive integer

Error message

caveman agent: output maxTokens must be a positive integer

What it means

Thrown by the output() builder when maxTokens is not a safe integer greater than zero. maxTokens is the hard output allowance for the model's final answer, so 0, negatives, fractions, NaN, and numeric strings are invalid — unlike artifact's cap there is no meaningful zero case.

Source

Thrown at packages/agent/src/primitives.ts:404

    kind: "artifact",
    strategy: options.strategy ?? "page",
    maxInlineTokens,
    recovery: options.recovery ?? "exact_ccr",
  });
}

export interface OutputDefinition<TSchemaValue extends TSchema | undefined = TSchema | undefined> {
  readonly kind: "output";
  readonly maxTokens: number;
  readonly schema?: TSchemaValue;
}

export function output<T extends TSchema | undefined = undefined>(options: {
  maxTokens: number;
  schema?: T;
}): OutputDefinition<T> {
  if (!Number.isSafeInteger(options.maxTokens) || options.maxTokens <= 0) {
    throw new Error("caveman agent: output maxTokens must be a positive integer");
  }
  return Object.freeze({
    kind: "output",
    maxTokens: options.maxTokens,
    ...(options.schema === undefined ? {} : { schema: options.schema }),
  }) as OutputDefinition<T>;
}

export type QualityGrader =
  | { type: "contains"; fragments: string[] }
  | { type: "tool_called"; tools: string[] }
  | { type: "exact_match"; expected: string }
  | { type: "json_schema"; schema: TSchema };

export type EvalGuardrail =
  | { type: "latency_threshold"; p95_ms: number }
  | { type: "error_rate"; max: number };

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Pass a positive integer such as maxTokens: 4096
  2. Clamp computed values: maxTokens: Math.max(1, Math.trunc(derived))
  3. Coerce and validate numeric config with Number.isSafeInteger(v) && v > 0 before calling output()

Example fix

// before
output({ maxTokens: Number(cfg.maxOutput) }); // cfg.maxOutput = '2,000'

// after
output({ maxTokens: Math.max(1, Math.trunc(Number(String(cfg.maxOutput).replace(/,/g, '')))) });
Defensive patterns

Strategy: validation

Validate before calling

function toMaxTokens(raw: unknown): number {
  const n = typeof raw === 'number' ? raw : Number(raw);
  if (!Number.isSafeInteger(n) || n <= 0) throw new Error(`maxTokens must be a positive integer, got ${String(raw)}`);
  return n;
}

Type guard

function isOutputMaxTokens(value: unknown): value is number { return typeof value === 'number' && Number.isSafeInteger(value) && value > 0; }

Prevention

When it happens

Trigger: Calling output({ maxTokens: 0 }), -500, 1024.5, NaN, Infinity, or maxTokens: '2000' from unparsed config.

Common situations: Deriving maxTokens from a model limit by multiplication and passing the fraction; copying a provider's default that happens to be a string in JSON config; using 0 to mean 'provider default' — here you must supply a positive integer yourself.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/a265e5bb150e7ade. Report an issue: GitHub.