{"record":{"id":"e2f4e6af4de5a259","repo":"JuliusBrussee/caveman","slug":"caveman-agent-file-path-is-required","errorCode":null,"errorMessage":"caveman agent: file path is required","messagePattern":"caveman agent: file path is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/primitives.ts","lineNumber":21,"sourceCode":"  StandardJSONSchemaV1,\n  StandardSchemaV1,\n} from \"@standard-schema/spec\";\n\nexport const AUTO = Symbol.for(\"@caveman-ai/agent:auto\");\nexport type Auto = { readonly kind: \"auto\"; readonly [AUTO]: true };\n\nexport function auto(): Auto {\n  return Object.freeze({ kind: \"auto\", [AUTO]: true as const });\n}\n\nexport interface FileSource {\n  readonly kind: \"file\";\n  readonly path: string;\n}\n\nexport function file(path: string): FileSource {\n  if (typeof path !== \"string\" || path.trim() === \"\") {\n    throw new Error(\"caveman agent: file path is required\");\n  }\n  return Object.freeze({ kind: \"file\", path });\n}\n\nexport const schema = {\n  any: () => Type.Any(),\n  array: <T extends TSchema>(items: T) => Type.Array(items),\n  boolean: () => Type.Boolean(),\n  integer: () => Type.Integer(),\n  literal: <T extends string | number | boolean>(value: T) => Type.Literal(value),\n  number: () => Type.Number(),\n  object: <T extends Record<string, TSchema>>(properties: T) => Type.Object(properties),\n  optional: <T extends TSchema>(value: T) => Type.Optional(value),\n  string: () => Type.String(),\n  union: <T extends TSchema[]>(values: [...T]) => Type.Union(values),\n};\n\nexport type ToolEffect = \"read\" | \"write\" | \"idempotent\" | \"external\";","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/primitives.ts#L3-L39","documentation":"The file() primitive constructs a frozen FileSource for the agent and validates its input up front. It throws when the path argument is not a non-empty string (after trimming whitespace). The library refuses to create a file source with no usable path so failures surface at the call site rather than deep in execution.","triggerScenarios":"file(\"\") , file(\"   \"), file(undefined as unknown as string), file(null), or any non-string value passed to file().","commonSituations":"Config/env variable that supplies the file path is unset or whitespace-only; a template/interpolation produced an empty string; a caller passed a Buffer, URL, or options object instead of a string path.","solutions":["Pass a non-empty string path to file(), e.g. file(\"src/config.json\")","Check the variable feeding the path — read it from env/config with a default and trim it before calling","Convert non-string path values (URL, Buffer) to a string path first with String(url) or url.pathname"],"exampleFix":"// before\nconst src = file(process.env.CONFIG_PATH); // undefined -> throws\n// after\nconst p = process.env.CONFIG_PATH?.trim();\nif (!p) throw new Error(\"CONFIG_PATH not set\");\nconst src = file(p);","handlingStrategy":"validation","validationCode":"function validFilePath(p: unknown): p is string {\n  return typeof p === \"string\" && p.trim() !== \"\";\n}\nif (!validFilePath(rawPath)) throw new Error(\"path required\");","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  const src = file(path);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"file path is required\")) {\n    // surface config problem: path was empty or not a string\n  } else throw err;\n}","preventionTips":["Trim and check env/config-supplied paths before calling file()","Use typed config loading so path fields are validated as non-empty strings at startup","Avoid passing URL/Buffer objects where a string path is expected"],"tags":["validation","arguments","empty-value"],"backgroundTag":"empty-required-field","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}