SigNoz/signoz · warning · errors.SignozError
CodeInternal
CodeInternal
Error message
error writing to cache
What it means
Returned by the in-memory (ristretto) cache Set when SetWithTTL returns false, meaning ristretto declined to admit the entry (its admission policy rejected it, or the cache was closed). The library surfaces this as an internal error rather than silently dropping the entry.
Source
Thrown at pkg/cache/memorycache/provider.go:124
if err != nil {
return err
}
// To make sure ristretto does not go into no-op
if ttl < 0 {
provider.settings.Logger().WarnContext(ctx, "ttl is less than 0, setting it to 0")
ttl = 0
}
if cloneable, ok := data.(cachetypes.Cloneable); ok {
cost := max(cloneable.Cost(), 1)
// Clamp to a minimum of 1: ristretto treats cost 0 specially and we
// never want zero-size entries to bypass admission accounting.
span.SetAttributes(attribute.Bool("memory.cloneable", true))
span.SetAttributes(attribute.Int64("memory.cost", cost))
toCache := cloneable.Clone()
if ok := provider.cc.SetWithTTL(strings.Join([]string{orgID.StringValue(), cacheKey}, "::"), toCache, cost, ttl); !ok {
return errors.New(errors.TypeInternal, errors.CodeInternal, "error writing to cache")
}
provider.cc.Wait()
return nil
}
toCache, err := provider.marshalBinary(ctx, data)
if err != nil {
return err
}
cost := max(int64(len(toCache)), 1)
span.SetAttributes(attribute.Bool("memory.cloneable", false))
span.SetAttributes(attribute.Int64("memory.cost", cost))
if ok := provider.cc.SetWithTTL(strings.Join([]string{orgID.StringValue(), cacheKey}, "::"), toCache, cost, ttl); !ok {
return errors.New(errors.TypeInternal, errors.CodeInternal, "error writing to cache")
}View on GitHub (pinned to 5069bf80b0)
Solutions
- Increase the memory cache capacity/numCounters tuning so ristretto admits your entries
- Cache smaller objects, or check entry sizes vs configured max cost
- Avoid Set calls after Close; guard lifecycle in shutdown paths
- If dropping entries is acceptable, treat this error as non-fatal and log-and-continue
Example fix
// after: tolerate admission rejection (log instead of fail)
if err := cache.Set(ctx, orgID, key, val, ttl); err != nil {
if err.Error() == "error writing to cache" {
log.Warn("cache admission rejected", "key", key)
} else { return err }
} Defensive patterns
Strategy: fallback
Type guard
func isCacheAdmissionErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "error writing to cache")
} Try / catch
if err := cache.Set(ctx, orgID, key, v, ttl); err != nil {
if isCacheAdmissionErr(err) {
log.Warn("cache admission rejected; continuing without caching", "key", key)
} else {
return err
}
} Prevention
- Size the memory cache for your largest entries; treat cache as best-effort in read paths
- Don't call Set after Close; wire cache lifecycle into service shutdown
When it happens
Trigger: Calling Set on a Cloneable cacheable value whose entry ristretto rejects — cost exceeds capacity, the item is frequently rejected by the admission policy, or the cache was shut down mid-write.
Common situations: Cache capacity configured too small for large span/trace objects; many concurrent sets with tiny TTLs; calling Set after cache Close in tests or during shutdown; KeepUntil/eviction pressure.
Related errors
AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28).
Data as JSON: /api/errors/f9052f514df47827.
Report an issue: GitHub.