{"record":{"id":"f1cba4df503b8d28","repo":"dagger/dagger","slug":"encode-persisted-cache-volume-nil-cache-volume","errorCode":null,"errorMessage":"encode persisted cache volume: nil cache volume","messagePattern":"encode persisted cache volume: nil cache volume","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/cache.go","lineNumber":310,"sourceCode":"\tref := entry.ref\n\ts.mu.Unlock()\n\n\treturn ref.Release(ctx)\n}\n\ntype persistedCacheVolumePayload struct {\n\tKey            string           `json:\"key\"`\n\tNamespace      string           `json:\"namespace,omitempty\"`\n\tSourceResultID uint64           `json:\"sourceResultID,omitempty\"`\n\tSharing        CacheSharingMode `json:\"sharing,omitempty\"`\n\tOwner          string           `json:\"owner,omitempty\"`\n\tSelector       string           `json:\"selector,omitempty\"`\n}\n\nfunc (cache *CacheVolume) EncodePersistedObject(ctx context.Context, persistedCache dagql.PersistedObjectCache) (dagql.PersistedObjectEncoding, error) {\n\t_ = ctx\n\tif cache == nil {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted cache volume: nil cache volume\")\n\t}\n\tvar sourceResultID uint64\n\tif cache.Source.Valid {\n\t\tencoded, err := encodePersistedObjectRef(persistedCache, cache.Source.Value, \"cache volume source\")\n\t\tif err != nil {\n\t\t\treturn dagql.PersistedObjectEncoding{}, err\n\t\t}\n\t\tsourceResultID = encoded\n\t}\n\tcache.mu.Lock()\n\tselector := cache.selector\n\tif selector == \"\" {\n\t\tselector = \"/\"\n\t}\n\tsnapshotID := cache.snapshotID\n\tvar snapshotLinks []dagql.PersistedSnapshotRefLink\n\tif cache.snapshot != nil {\n\t\tsnapshotID = cache.snapshot.SnapshotID()","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/cache.go#L292-L328","documentation":"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.","triggerScenarios":"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.","commonSituations":"Typed-nil through interfaces in engine code; query results where the cache volume was never constructed; stale/legacy persisted payloads decoded into nil objects.","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."],"exampleFix":"// before\nenc, err := cache.EncodePersistedObject(ctx, persistedCache) // cache is nil\n// after\nif cache == nil {\n    return dagql.PersistedObjectEncoding{}, fmt.Errorf(\"no cache volume to persist\")\n}\nenc, err := cache.EncodePersistedObject(ctx, persistedCache)","handlingStrategy":"type-guard","validationCode":"if cache == nil {\n    return dagql.PersistedObjectEncoding{}, fmt.Errorf(\"cache volume not initialized\")\n}\nenc, err := cache.EncodePersistedObject(ctx, persistedCache)","typeGuard":"func isPersistableCacheVolume(cv *CacheVolume) bool {\n    return cv != nil && cv.Key != \"\"\n}","tryCatchPattern":"enc, err := cache.EncodePersistedObject(ctx, persistedCache)\nif err != nil {\n    if strings.Contains(err.Error(), \"nil cache volume\") {\n        // skip persistence or construct the volume here\n    }\n    return err\n}","preventionTips":["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"],"tags":["cache-volume","nil-reference","serialization","dagger-engine"],"backgroundTag":"nil-reference","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}