{"record":{"id":"862971f225b8da39","repo":"golangci/golangci-lint","slug":"failed-to-gob-decode-w","errorCode":null,"errorMessage":"failed to gob decode: %w","messagePattern":"failed to gob decode: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cache/cache.go","lineNumber":287,"sourceCode":"\nfunc (c *Cache) encode(data any) (*bytes.Buffer, error) {\n\tbuf := &bytes.Buffer{}\n\terr := c.sw.TrackStageErr(\"gob\", func() error {\n\t\treturn gob.NewEncoder(buf).Encode(data)\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to gob encode: %w\", err)\n\t}\n\n\treturn buf, nil\n}\n\nfunc (c *Cache) decode(b []byte, data any) error {\n\terr := c.sw.TrackStageErr(\"gob\", func() error {\n\t\treturn gob.NewDecoder(bytes.NewReader(b)).Decode(data)\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to gob decode: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc SetSalt(b *bytes.Buffer) {\n\tcache.SetSalt(b.Bytes())\n}\n\nfunc DefaultDir() (string, error) {\n\tcacheDir, _, err := cache.DefaultDir()\n\treturn cacheDir, err\n}\n","sourceCodeStart":269,"sourceCodeEnd":301,"githubUrl":"https://github.com/golangci/golangci-lint/blob/ed7a235d2d771152056fdc142a9855567c5796a9/internal/cache/cache.go#L269-L301","documentation":"internal/cache.Cache.decode wraps any error returned by gob decoding of cached bytes into \"failed to gob decode: %w\". It is thrown when the stored byte buffer cannot be decoded into the requested value, and it is instrumented via sw.TrackStageErr under the \"gob\" stage. The caller (Cache.Get) surfaces this when a cache entry exists but is unreadable.","triggerScenarios":"Cache.Get hit an existing entry and decode() called gob.NewDecoder(bytes.NewReader(b)).Decode(data), but the bytes are not valid gob data or do not match the target type.","commonSituations":"Cache files written by a different version of the app (struct fields/types changed between releases, so gob type names no longer match); corrupted or truncated cache files (crash mid-write, disk issues); manually edited cache files; decoding into a different Go type than was encoded.","solutions":["Delete the stale/corrupt cache directory (e.g. the app's cache command or manually remove the cache dir) so entries are regenerated","Ensure the type passed to Decode matches the type that was gob-encoded; gob is type-strict about struct names and exported fields","Bump a cache format/version key so old entries written by incompatible versions are ignored instead of decoded","Check the wrapped error (%w) for the exact gob failure: 'unexpected EOF' means truncation, 'type mismatch' means schema drift"],"exampleFix":"// before\ncacheDir, _ := cache.DefaultDir()\n_ = os.ReadFile(filepath.Join(cacheDir, key)) // decodes stale v1 gob data\n\n// after\n// include format version in cache key so old gob payloads are never decoded\ndb.Get(filepath.Join(\"v2\", key), &out) // or purge: os.RemoveAll(cacheDir)","handlingStrategy":"fallback","validationCode":"if len(b) == 0 {\n    return nil, fmt.Errorf(\"cache entry empty, skipping decode\")\n}\n// optionally verify a stored format version prefix before decoding\nif !bytes.HasPrefix(b, []byte(cacheFormatV2)) {\n    return nil, fmt.Errorf(\"cache format version mismatch\")\n}","typeGuard":"func isGobDecodeError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"failed to gob decode\")\n}","tryCatchPattern":"if err := cache.Get(ctx, key, &out); err != nil {\n    if isGobDecodeError(err) {\n        log.Printf(\"corrupt/stale cache entry %q: %v — regenerating\", key, err)\n        _ = cache.Invalidate(ctx, key)\n        out = recompute() // fall back to recomputation\n    } else {\n        return err\n    }\n}","preventionTips":["Include a format/version string in cache keys so entries from incompatible versions are never decoded","Treat any decode error as a cache miss and recompute rather than failing the operation","Keep gob-encoded structs' exported field names stable across releases, or bump the version key when they change","Write cache files atomically (temp file + rename) to avoid truncated entries"],"tags":["gob","cache","decoding"],"backgroundTag":"gob-decode-failed","analyzedSha":"ed7a235d2d771152056fdc142a9855567c5796a9","analyzedAt":"2026-09-02T18:47:33.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}