JuliusBrussee/caveman · error
ccr: typed object session_id is required
Error message
ccr: typed object session_id is required
What it means
Validation error from prepareObject in the CCR typed-object path: every typed Object must carry a non-blank SessionID, and unknown/blank values fail closed. PutObject refuses to store the object without it because session scoping is part of the object's identity and retrieval semantics.
Solutions
- Set obj.SessionID to the active session's ID before calling PutObject.
- Add a constructor/helper that requires sessionID so it cannot be omitted.
- If unmarshaling from JSON, validate session_id is present and non-empty before PutObject.
- Trim and check strings.TrimSpace(sessionID) != "" at the call site.
Example fix
// before
obj := ccr.Object{Type: ccr.TypeToolResult, Data: data}
handle, err := store.PutObject(obj)
// after
obj := ccr.Object{Type: ccr.TypeToolResult, Data: data, SessionID: session.ID}
if strings.TrimSpace(obj.SessionID) == "" { return errors.New("missing session id") }
handle, err := store.PutObject(obj) Defensive patterns
Strategy: validation
Validate before calling
func validObject(o ccr.Object) bool {
return strings.TrimSpace(o.SessionID) != ""
} Try / catch
if err := ensureSessionID(&obj, session.ID); err != nil { return err }
if _, err := store.PutObject(obj); err != nil {
if strings.Contains(err.Error(), "session_id is required") {
return fmt.Errorf("object rejected: %w", err)
}
return err
} Prevention
- Construct objects via a helper that takes sessionID as a required parameter.
- Validate JSON payloads include session_id before PutObject.
- Trim session IDs; reject whitespace-only values early.
- Add a unit test asserting PutObject fails on empty SessionID.
When it happens
Trigger: Calling PutObject/putObject with Object{...} where SessionID is "" or whitespace-only; constructing objects programmatically and forgetting to propagate the session context.
Common situations: Background/worker code creating objects without the request's session ID; refactoring that dropped a field from the struct literal; deserializing objects from JSON where session_id was omitted.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ccr: typed object byte lengths cannot be negative
- cave_provider_identity_missing
- CAVEMAN_CCR_MAX_BYTES must be a positive integer
- ccr: typed object content_hash does not match data
- rewriter: model is required
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/494eddd442d699e5.
Report an issue: GitHub.
Appendix: source
Thrown at engine/ccr/store.go:110
OriginalByteLength int `json:"original_byte_length"`
StoredByteLength int `json:"stored_byte_length"`
Data []byte `json:"data"`
}
var objectTypes = map[ObjectType]struct{}{
ObjectFileObservation: {}, ObjectSearchResult: {}, ObjectCommandResult: {},
ObjectTestResult: {}, ObjectBuildResult: {}, ObjectDiffSnapshot: {},
ObjectTaskContract: {}, ObjectTaskDecision: {}, ObjectExecutionState: {},
ObjectDocumentationExcerpt: {}, ObjectBrowserSnapshot: {},
ObjectRepositoryMap: {}, ObjectEvidenceBundle: {},
}
func prepareObject(obj Object) (Object, error) {
if _, ok := objectTypes[obj.Type]; !ok {
return Object{}, fmt.Errorf("ccr: unknown object type %q", obj.Type)
}
if strings.TrimSpace(obj.SessionID) == "" {
return Object{}, errors.New("ccr: typed object session_id is required")
}
if obj.Currentness == "" {
obj.Currentness = Current
}
if obj.Currentness != Current && obj.Currentness != Stale && obj.Currentness != Archived {
return Object{}, fmt.Errorf("ccr: unknown currentness %q", obj.Currentness)
}
if obj.Lifecycle == "" {
obj.Lifecycle = Hot
}
if obj.Lifecycle != Hot && obj.Lifecycle != Warm && obj.Lifecycle != Cold && obj.Lifecycle != LifecycleArchived {
return Object{}, fmt.Errorf("ccr: unknown lifecycle %q", obj.Lifecycle)
}
if obj.CreatedAt.IsZero() {
obj.CreatedAt = time.Now().UTC()
} else {
obj.CreatedAt = obj.CreatedAt.UTC()
}View on GitHub (pinned to 3ee70a1026)