JuliusBrussee/caveman · error · Error

caveman agent: file path is required

Error message

caveman agent: file path is required

What it means

file(path) constructs a frozen FileSource descriptor ({ kind: "file", path }) used to mark tool outputs or references backed by files. It refuses anything that is not a non-empty string after trimming, because an empty/whitespace path would produce a meaningless artifact reference. The check is on the argument's shape, not on filesystem existence.

Source

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

  StandardJSONSchemaV1,
  StandardSchemaV1,
} from "@standard-schema/spec";

export const AUTO = Symbol.for("@caveman-ai/agent:auto");
export type Auto = { readonly kind: "auto"; readonly [AUTO]: true };

export function auto(): Auto {
  return Object.freeze({ kind: "auto", [AUTO]: true as const });
}

export interface FileSource {
  readonly kind: "file";
  readonly path: string;
}

export function file(path: string): FileSource {
  if (typeof path !== "string" || path.trim() === "") {
    throw new Error("caveman agent: file path is required");
  }
  return Object.freeze({ kind: "file", path });
}

export const schema = {
  any: () => Type.Any(),
  array: <T extends TSchema>(items: T) => Type.Array(items),
  boolean: () => Type.Boolean(),
  integer: () => Type.Integer(),
  literal: <T extends string | number | boolean>(value: T) => Type.Literal(value),
  number: () => Type.Number(),
  object: <T extends Record<string, TSchema>>(properties: T) => Type.Object(properties),
  optional: <T extends TSchema>(value: T) => Type.Optional(value),
  string: () => Type.String(),
  union: <T extends TSchema[]>(values: [...T]) => Type.Union(values),
};

export type ToolEffect = "read" | "write" | "idempotent" | "external";

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Guard before calling: if (!path?.trim()) throw your own descriptive error naming the missing option
  2. Default the value: file(path ?? "out.txt")
  3. Fix the upstream variable that produced the empty string (usually an undefined option)
  4. Add schema validation on your CLI/config layer so empty paths fail early with context

Example fix

// before
const src = file(args.file); // args.file is undefined when flag omitted

// after
if (!args.file?.trim()) throw new Error("--file is required");
const src = file(args.file);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof path !== "string" || path.trim() === "") {
  throw new Error("output file path is required (did you forget --file?)");
}
const src = file(path);

Type guard

const isNonEmptyString = (v: unknown): v is string =>
  typeof v === "string" && v.trim() !== "";

Prevention

When it happens

Trigger: Calling file(""), file(" "), or file(undefined/null/number) — commonly when a computed filename turns out to be empty because an upstream variable was undefined.

Common situations: Passing options.outputFile straight from CLI args where the flag was omitted, template strings that interpolate undefined (file(`${dir}/${name}`) with name undefined yields "dir/undefined" — that passes but is a smell; fully empty yields the throw), or destructuring a missing field.

Related errors


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