JuliusBrussee/caveman · error
cacheengine: invalid partition key
Error message
cacheengine: invalid partition key
What it means
Thrown by validatePlanRequest when request.PartitionKey fails validIdentity(key, 4096, true): it must be at most 4096 bytes and contain only characters accepted by the identity validator (empty is allowed because the flag is 'optional'). The partition key shards cache entries, so a malformed key would corrupt shard routing.
Source
Thrown at cacheengine/engine.go:276
ProfileID: profile.ID,
Mode: profile.Mode,
Attribution: profile.Attribution,
PrefixSHA256: result.PrefixSHA256,
EconomicsBasis: economicsBasis,
KeyShardCount: 1,
Warnings: warnings,
}, nil
}
func validatePlanRequest(request PlanRequest) error {
if !validIdentity(request.Scope, 4096, false) {
return errors.New("cacheengine: invalid scope")
}
if !validIdentity(request.Epoch, 4096, false) {
return errors.New("cacheengine: invalid epoch")
}
if !validIdentity(request.PartitionKey, 4096, true) {
return errors.New("cacheengine: invalid partition key")
}
if request.ExpectedCalls < 0 || request.ExpectedRequestsPerMinute < 0 {
return errors.New("cacheengine: negative traffic expectation")
}
profile := normalizedProfile(request.Profile)
if !validIdentity(profile.ID, 256, false) || !validIdentity(profile.Provider, 64, true) || !validIdentity(profile.OptimizerID, 256, true) {
return errors.New("cacheengine: invalid profile identity")
}
if profile.Mode != ModeUnsupported && profile.Mode != ModeImplicit && profile.Mode != ModeAffinity && profile.Mode != ModeExplicit {
return fmt.Errorf("cacheengine: unknown mode %q", profile.Mode)
}
if profile.Mode != ModeUnsupported {
if profile.MaxBreakpoints <= 0 || profile.MinPrefixTokens < 0 || profile.MaxRPMPerKey < 0 || profile.TTL < 0 {
return errors.New("cacheengine: invalid cache thresholds")
}
switch profile.Attribution {
case AttributionNone, AttributionOrganic, AttributionAffinity, AttributionCausal:
default:View on GitHub (pinned to 27d5a3981a)
Solutions
- Shrink or hash the partition key (e.g. hex(sha256(rawKey))) so it stays under 4096 bytes
- Inspect PartitionKey for control characters or invalid UTF-8 before the call and sanitize it
- If the key is derived from user input, truncate or map it through a fixed-size identifier
Example fix
// before
req := cacheengine.PlanRequest{Scope: scope, Epoch: epoch, PartitionKey: tenantID + ":" + rawUserPrompt}
// after
sum := sha256.Sum256([]byte(tenantID + ":" + rawUserPrompt))
req := cacheengine.PlanRequest{Scope: scope, Epoch: epoch, PartitionKey: tenantID + ":" + hex.EncodeToString(sum[:])} Defensive patterns
Strategy: validation
Validate before calling
func validPartitionKey(k string) bool {
return len(k) <= 4096 // plus the identity charset used for PartitionKey (optional -> empty ok)
} Type guard
func isPartitionKeySafe(k string) bool { return len(k) <= 4096 && utf8.ValidString(k) } Try / catch
if err := engine.Plan(req); err != nil {
if strings.Contains(err.Error(), "invalid partition key") { /* rehash/shrink key, retry once */ }
return err
} Prevention
- Hash or truncate key material derived from unbounded user input
- Never paste whole prompts or URLs into the partition key
When it happens
Trigger: Calling the engine's Plan entry point with a PartitionKey longer than 4096 bytes, containing characters outside the accepted identity charset, or otherwise failing validIdentity (e.g. control characters, invalid UTF-8) while Scope and Epoch already passed.
Common situations: Building the partition key by concatenating unbounded user data (tenant + session + prompt hash), passing a full prompt or URL as the key, or an encoding bug that embeds raw bytes/NULs into the key.
Related errors
- cacheengine: negative traffic expectation
- cacheengine: invalid profile identity
- cacheengine: invalid cache thresholds
- cacheengine: invalid cache economics
- cacheengine: stable segment needs name and content
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/115568af233fdbc0.
Report an issue: GitHub.