{"record":{"id":"beb1b155307d6b00","repo":"restic/restic","slug":"decompressing-blob-v-from-pack-v-failed-w","errorCode":null,"errorMessage":"decompressing blob %v from pack %v failed: %w","messagePattern":"decompressing blob (.+?) from pack (.+?) failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/repository/repository.go","lineNumber":1334,"sourceCode":"\n\tif int(entry.Length) <= b.key.NonceSize() {\n\t\tdebug.Log(\"%v\", b.blobs)\n\t\treturn packBlobValue{}, fmt.Errorf(\"invalid blob length %v\", entry)\n\t}\n\n\t// decryption errors are likely permanent, give the caller a chance to skip them\n\tnonce, ciphertext := buf[:b.key.NonceSize()], buf[b.key.NonceSize():]\n\tplaintext, err := b.key.Open(ciphertext[:0], nonce, ciphertext, nil)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"decrypting blob %v from pack %v failed: %w\", h, b.packID.String(), err)\n\t}\n\tif err == nil && entry.IsCompressed() {\n\t\t// DecodeAll will allocate a slice if it is not large enough since it\n\t\t// knows the decompressed size (because we're using EncodeAll)\n\t\tb.decode, err = b.dec.DecodeAll(plaintext, b.decode[:0])\n\t\tplaintext = b.decode\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"decompressing blob %v from pack %v failed: %w\", h, b.packID.String(), err)\n\t\t}\n\t}\n\tif err == nil {\n\t\tid := restic.Hash(plaintext)\n\t\tif !id.Equal(entry.ID) {\n\t\t\tdebug.Log(\"read blob %v/%v from pack %v: wrong data returned, hash is %v\",\n\t\t\t\th.Type, h.ID, b.packID.String(), id)\n\t\t\terr = fmt.Errorf(\"read blob %v from pack %v: wrong data returned, hash is %v\",\n\t\t\t\th, b.packID.String(), id)\n\t\t}\n\t}\n\n\treturn packBlobValue{entry.BlobHandle, plaintext, err}, nil\n}\n\nfunc (r *Repository) zeroChunk() restic.ID {\n\tr.zeroChunkOnce.Do(func() {\n\t\tr.zeroChunkID = restic.Hash(make([]byte, chunker.MinSize))","sourceCodeStart":1316,"sourceCodeEnd":1352,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/repository/repository.go#L1316-L1352","documentation":"zstd DecodeAll failed on a blob whose header entry has the compression flag set, so after successful decryption the payload is not valid zstd data. This means the compressed plaintext is damaged (bitrot that still decrypts is rare because MAC failure would fire first, so typically the entry flags and the stored bytes disagree) or the blob was written uncompressed while flagged compressed. Thrown from packBlobIterator.Next during any pack-reading operation.","triggerScenarios":"A pack header entry flagged IsCompressed whose blob bytes are raw/uncompressed (mixed-version writer bug, manual pack surgery); corruption of the blob body in a way that preserves authentication is not possible under the MAC, so in practice the entry metadata is the corrupted part; reading v2-compressed packs with a mismatched index.","commonSituations":"Repositories touched by prerelease or mismatched restic versions during the compression feature rollout; indexes rebuilt incorrectly so blob lengths/flags point into the middle of another blob.","solutions":["Run restic check --read-data to identify the affected packs","Rebuild the index (restic rebuild-index) so entry metadata matches actual pack headers","Recover the pack from a second copy or backend versioning","Re-backup affected data and prune the damaged pack"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"decompressing blob\") {\n    // entry metadata disagrees with stored bytes; rebuild index and re-verify\n    log.Printf(\"pack %s: blob %v fails zstd decode — run restic rebuild-index then restic check\", packID, h.ID.Str())\n    return nil // skip in scan mode\n}","preventionTips":["Do not mix restic versions from the compression-feature development window on one repo","Verify repository integrity (restic check) before and after migrations or major version upgrades","Treat index rebuilds on unverified packs as suspect; prefer check first"],"tags":["go","restic","compression","zstd","corruption"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}