JuliusBrussee/caveman · error · Error
caveman agent: invalid tool name ${JSON.stringify(options.na
Error message
caveman agent: invalid tool name ${JSON.stringify(options.name)} What it means
The tool() factory validates that the tool name matches /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/ — it must start with a letter and contain only letters, digits, underscores, and hyphens, max 128 chars. This keeps names compatible with model function-calling constraints across providers. Any other shape (spaces, dots, leading digits, unicode, empty) throws at definition time with the offending name JSON-stringified.
Source
Thrown at packages/agent/src/primitives.ts:129
inputJSONSchema?: never;
}
export function tool<TInput extends TSchema, TResult>(
options: ToolOptions<TInput, TResult>,
): ToolDefinition<Static<TInput>, TResult>;
export function tool<Input, Output, TResult>(
options: StandardToolOptions<Input, Output, TResult>,
): ToolDefinition<Output, TResult>;
export function tool<Input, Output, TResult>(
options: StandardJSONToolOptions<Input, Output, TResult>,
): ToolDefinition<Output, TResult>;
export function tool(
options: ToolOptions<TSchema, unknown> |
StandardToolOptions<unknown, unknown, unknown> |
StandardJSONToolOptions<unknown, unknown, unknown>,
): ToolDefinition<unknown, unknown> {
if (!/^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(options.name)) {
throw new Error(`caveman agent: invalid tool name ${JSON.stringify(options.name)}`);
}
if (!["read", "write", "idempotent", "external"].includes(options.effect)) {
throw new Error(`caveman agent: unknown tool effect ${JSON.stringify(options.effect)}`);
}
const result = typeof options.result === "object"
? artifactResultPolicy(options.result)
: options.result ?? "auto";
if (!["auto", "inline", "page", "compress", "exact_ccr"].includes(result)) {
throw new Error(`caveman agent: unknown tool result policy ${JSON.stringify(result)}`);
}
const timeoutMs = options.timeoutMs ?? 30_000;
if (!Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {
throw new Error("caveman agent: tool timeoutMs must be a positive integer");
}
const standard = standardToolSchema(options.input);
let input: TSchema;
if (standard === undefined) {
input = options.input as TSchema;View on GitHub (pinned to 27d5a3981a)
Solutions
- Rename the tool to match the pattern, e.g. "fs_read_file" or "searchFiles"
- Slugify generated names: name.replace(/[^a-zA-Z0-9_-]+/g, "_").replace(/^[^a-zA-Z]+/, "").slice(0, 128)
- Validate user-provided tool names at your own boundary and reject early with better context
- Keep a constant table of tool names instead of deriving them dynamically
Example fix
// before
const t = tool({ name: "fs.readFile", effect: "read", execute: ... });
// after
const t = tool({ name: "fs_read_file", effect: "read", execute: ... }); Defensive patterns
Strategy: validation
Validate before calling
const TOOL_NAME_RE = /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/;
function safeToolName(raw: string): string {
const name = raw.replace(/[^a-zA-Z0-9_-]+/g, "_").replace(/^[^a-zA-Z]+/, "").slice(0, 128);
if (!TOOL_NAME_RE.test(name)) throw new Error(`cannot derive valid tool name from ${JSON.stringify(raw)}`);
return name;
} Type guard
const isValidToolName = (name: string): boolean =>
/^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(name); Prevention
- Define tool names as constants, not derived strings
- Validate user-supplied tool names before registration and surface your own error message
- Remember the 128-character cap when generating names from templates
When it happens
Trigger: Naming a tool "fs.readFile", "search files", "2fa_check", "", "my tool!", or a name longer than 128 characters. The validation happens synchronously inside tool(), so the throw occurs during setup, not during a run.
Common situations: Deriving tool names from user input, file names, or i18n strings; converting an OpenAI-style function name with dots; or generating names from templates that occasionally emit an empty suffix.
Related errors
- caveman agent: file path is required
- caveman agent: unknown tool effect ${JSON.stringify(options.
- caveman agent: unknown tool result policy ${JSON.stringify(r
- caveman agent: tool timeoutMs must be a positive integer
- caveman agent: Standard Schema emitted invalid input JSON Sc
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/27d492768c5bfa95.
Report an issue: GitHub.