{"record":{"id":"4d09f97b8808e1bd","repo":"JuliusBrussee/caveman","slug":"caveman-agent-context-id-is-required","errorCode":null,"errorMessage":"caveman agent: context id is required","messagePattern":"caveman agent: context id is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/primitives.ts","lineNumber":348,"sourceCode":"  readonly privacy: PrivacyClass;\n  readonly opaque: boolean;\n  readonly ttlTurns?: number;\n}\n\nexport function context(options: {\n  id: string;\n  kind: ContextKind;\n  source: string | FileSource;\n  stability: ContextStability;\n  safety?: SafetyClass;\n  priority?: ContextPriority;\n  recovery?: RecoveryKind;\n  cacheRegion?: CacheRegion;\n  privacy?: PrivacyClass;\n  opaque?: boolean;\n  ttlTurns?: number;\n}): ContextDefinition {\n  if (options.id.trim() === \"\") throw new Error(\"caveman agent: context id is required\");\n  if (options.ttlTurns !== undefined && (!Number.isSafeInteger(options.ttlTurns) || options.ttlTurns <= 0)) {\n    throw new Error(\"caveman agent: context ttlTurns must be a positive integer\");\n  }\n  const definition: ContextDefinition = {\n    kind: \"context\",\n    id: options.id,\n    segmentKind: options.kind,\n    source: options.source,\n    stability: options.stability,\n    safety: options.safety ?? \"S0\",\n    priority: options.priority ?? \"required\",\n    recovery: options.recovery ?? \"none\",\n    cacheRegion: options.cacheRegion ?? (options.stability === \"build\" ? \"frozen_prefix\" : \"live_zone\"),\n    privacy: options.privacy ?? \"local_sensitive\",\n    opaque: options.opaque ?? false,\n    ...(options.ttlTurns === undefined ? {} : { ttlTurns: options.ttlTurns }),\n  };\n  return Object.freeze(definition);","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/primitives.ts#L330-L366","documentation":"Thrown by the context() builder when options.id is empty or only whitespace (id.trim() === ''). Context ids key the segment in the Context IR and lock digest, so an untrimmable-to-nonempty id is rejected at definition time.","triggerScenarios":"Calling context({ id: '' }) or context({ id: '   \\t' }). Note that an id of whitespace-surrounded text like ' sys ' passes (only the trimmed value is checked), but blank strings do not.","commonSituations":"Generating ids from file paths or dynamic data where the source string is occasionally empty; template literals that interpolate an undefined variable into ''; config lists with a missing id field defaulting to empty.","solutions":["Give each context segment a stable non-empty id, e.g. 'system-prompt' or 'tool-docs'","When ids are generated, fall back to a derived default: options.id = raw?.trim() || fallbackName","Validate context definitions in config loading with a required-non-empty check before building the agent"],"exampleFix":"// before\ncontext({ id: fileName ?? '', kind: 'system', source: sys, stability: 'build' });\n\n// after\ncontext({ id: fileName?.trim() || 'system-main', kind: 'system', source: sys, stability: 'build' });","handlingStrategy":"validation","validationCode":"function requireContextId(raw: unknown, fallback?: string): string {\n  const id = typeof raw === 'string' ? raw.trim() : '';\n  if (id === '') { if (fallback) return fallback; throw new Error('context id is required'); }\n  return id;\n}","typeGuard":"function isNonEmptyContextId(value: unknown): value is string { return typeof value === 'string' && value.trim() !== ''; }","tryCatchPattern":null,"preventionTips":["Make context ids required in your config schema (minLength: 1)","Use stable human-readable ids so lock evidence stays diffable","Never derive ids solely from optional data"],"tags":["validation","context","required-field"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}