dagger/dagger · error
encode persisted cache volume: nil cache volume
Error message
encode persisted cache volume: nil cache volume
What it means
CacheVolume.EncodePersistedObject (core/cache.go:307) serializes a cache volume into a persisted-object payload for the dagql persistence layer; a nil *CacheVolume has nothing to encode, so it fails fast with this error. It is a defensive check against typed-nil receivers reaching persistence.
Source
Thrown at core/cache.go:310
ref := entry.ref
s.mu.Unlock()
return ref.Release(ctx)
}
type persistedCacheVolumePayload struct {
Key string `json:"key"`
Namespace string `json:"namespace,omitempty"`
SourceResultID uint64 `json:"sourceResultID,omitempty"`
Sharing CacheSharingMode `json:"sharing,omitempty"`
Owner string `json:"owner,omitempty"`
Selector string `json:"selector,omitempty"`
}
func (cache *CacheVolume) EncodePersistedObject(ctx context.Context, persistedCache dagql.PersistedObjectCache) (dagql.PersistedObjectEncoding, error) {
_ = ctx
if cache == nil {
return dagql.PersistedObjectEncoding{}, fmt.Errorf("encode persisted cache volume: nil cache volume")
}
var sourceResultID uint64
if cache.Source.Valid {
encoded, err := encodePersistedObjectRef(persistedCache, cache.Source.Value, "cache volume source")
if err != nil {
return dagql.PersistedObjectEncoding{}, err
}
sourceResultID = encoded
}
cache.mu.Lock()
selector := cache.selector
if selector == "" {
selector = "/"
}
snapshotID := cache.snapshotID
var snapshotLinks []dagql.PersistedSnapshotRefLink
if cache.snapshot != nil {
snapshotID = cache.snapshot.SnapshotID()View on GitHub (pinned to 82ba2681db)
Solutions
- Construct the CacheVolume via NewCache(key, namespace, source, sharing, owner) before persistence.
- At the call site, skip persistence when the cache volume is nil.
- Ensure Nullable fields are only encoded when Valid.
Example fix
// before
enc, err := cache.EncodePersistedObject(ctx, persistedCache) // cache is nil
// after
if cache == nil {
return dagql.PersistedObjectEncoding{}, fmt.Errorf("no cache volume to persist")
}
enc, err := cache.EncodePersistedObject(ctx, persistedCache) Defensive patterns
Strategy: type-guard
Validate before calling
if cache == nil {
return dagql.PersistedObjectEncoding{}, fmt.Errorf("cache volume not initialized")
}
enc, err := cache.EncodePersistedObject(ctx, persistedCache) Type guard
func isPersistableCacheVolume(cv *CacheVolume) bool {
return cv != nil && cv.Key != ""
} Try / catch
enc, err := cache.EncodePersistedObject(ctx, persistedCache)
if err != nil {
if strings.Contains(err.Error(), "nil cache volume") {
// skip persistence or construct the volume here
}
return err
} Prevention
- Construct CacheVolume with NewCache before any persistence call
- Guard Nullable fields — persist only when Valid
- Beware typed-nil pointers stored in interfaces in Go
- Add nil checks at API entry points for clearer errors
When it happens
Trigger: Calling EncodePersistedObject on a nil *CacheVolume — e.g. an unset Nullable CacheVolume field being persisted, or a Go interface holding a typed nil pointer reaching the persistence path.
Common situations: Typed-nil through interfaces in engine code; query results where the cache volume was never constructed; stale/legacy persisted payloads decoded into nil objects.
Related errors
- register cache volume snapshot: nil mutable ref
- marshal persisted cache volume payload: %w
- cache volume lock key: nil cache volume
- acquire cache volume snapshot %q: nil mutable ref
- acquire cache volume snapshot %q: opened snapshot %q
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/f1cba4df503b8d28.
Report an issue: GitHub.