{"record":{"id":"693b8077a33564df","repo":"JuliusBrussee/caveman","slug":"cacheengine-stable-segment-needs-name-and-content","errorCode":null,"errorMessage":"cacheengine: stable segment needs name and content","messagePattern":"cacheengine: stable segment needs name and content","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cacheengine/engine.go","lineNumber":332,"sourceCode":"\tif profile.MaxRPMPerKey == 0 {\n\t\tprofile.MaxRPMPerKey = 15\n\t}\n\tif profile.Attribution == \"\" {\n\t\tprofile.Attribution = AttributionNone\n\t}\n\treturn profile\n}\n\nfunc stablePrefix(segments []Segment, maxBytes int) ([]byte, []Segment, error) {\n\tvar prefix []byte\n\tvar stable []Segment\n\tseenNames := map[string]bool{}\n\tfor _, segment := range segments {\n\t\tif !segment.Stable || !segment.Cacheable {\n\t\t\tbreak\n\t\t}\n\t\tif !validIdentity(segment.Name, 1024, false) || len(segment.Content) == 0 || seenNames[segment.Name] {\n\t\t\treturn nil, nil, errors.New(\"cacheengine: stable segment needs name and content\")\n\t\t}\n\t\tseenNames[segment.Name] = true\n\t\tif segment.Tokens < 0 || segment.ExpectedCalls < 0 {\n\t\t\treturn nil, nil, errors.New(\"cacheengine: negative segment measurement\")\n\t\t}\n\t\tif maxBytes < 8 || len(segment.Name) > maxBytes-8 || len(segment.Content) > maxBytes-8-len(segment.Name) || len(prefix) > maxBytes-8-len(segment.Name)-len(segment.Content) {\n\t\t\treturn nil, nil, errors.New(\"cacheengine: stable prefix exceeds configured byte limit\")\n\t\t}\n\t\tif len(segment.Name) > math.MaxUint32 || len(segment.Content) > math.MaxUint32 {\n\t\t\treturn nil, nil, errors.New(\"cacheengine: segment exceeds framing limit\")\n\t\t}\n\t\tprefix = appendFrame(prefix, segment.Name, segment.Content)\n\t\tstable = append(stable, segment)\n\t}\n\treturn prefix, stable, nil\n}\n\nfunc appendFrame(dst []byte, name string, content []byte) []byte {","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/engine.go#L314-L350","documentation":"Thrown by stablePrefix while folding the leading run of Stable && Cacheable segments: a segment must have a valid non-empty Name (<= 1024 bytes, identity rules), non-empty Content, and a Name not seen earlier in the prefix. The loop stops at the first non-stable/non-cacheable segment, so only the head of the segment list is affected.","triggerScenarios":"Passing Segments where a leading stable/cacheable segment has Name == \"\" (or > 1024 bytes / bad charset), Content of zero length, or two leading stable segments sharing the same Name.","commonSituations":"Generating segment names from user content that can be empty; reusing a constant name like 'context' for multiple stable segments; forgetting that the system/description segment must carry content; whitespace-trimmed content becoming empty.","solutions":["Give every stable cacheable segment a unique, non-empty, <= 1024-byte identity-safe Name","Ensure Content is non-empty for each stable segment (skip the segment instead of sending it empty)","Deduplicate names by indexing them (e.g. 'context-1', 'context-2') if you legitimately repeat a kind of segment"],"exampleFix":"// before\nsegments := []cacheengine.Segment{{Name: \"docs\", Stable: true, Cacheable: true, Content: nil}}\n\n// after\nsegments := []cacheengine.Segment{{Name: \"docs-v2\", Stable: true, Cacheable: true, Content: docBytes}}","handlingStrategy":"validation","validationCode":"func stableSegmentsOK(segs []cacheengine.Segment) error {\n    seen := map[string]bool{}\n    for _, s := range segs {\n        if !s.Stable || !s.Cacheable { break }\n        if s.Name == \"\" || len(s.Name) > 1024 || len(s.Content) == 0 || seen[s.Name] { return fmt.Errorf(\"bad segment %q\", s.Name) }\n        seen[s.Name] = true\n    }\n    return nil\n}","typeGuard":"func isStableSegment(s cacheengine.Segment) bool { return s.Stable && s.Cacheable && s.Name != \"\" && len(s.Content) > 0 }","tryCatchPattern":null,"preventionTips":["Generate names deterministically from content identity (e.g. hash) to guarantee uniqueness","Skip empty segments instead of sending them"],"tags":["cacheengine","validation","segments","prefix","go"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}