{"record":{"id":"1e4541d2419c4639","repo":"abpframework/abp","slug":"the-encrypted-blob-is-corrupted-or-has-an-invalid-1e4541","errorCode":null,"errorMessage":"The encrypted BLOB is corrupted or has an invalid format: truncated chunk!","messagePattern":"The encrypted BLOB is corrupted or has an invalid format: truncated chunk!","errorType":"exception","errorClass":"AbpException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobEncryptionCodec.cs","lineNumber":531,"sourceCode":"        if (chunkIndex < 0)\n        {\n            // A wrapped chunk index would repeat a nonce for the same key, which breaks AES-GCM.\n            throw new AbpException(\"The data is too large: the maximum chunk count has been exceeded!\");\n        }\n\n        WriteInt32BigEndian(nonceOrAssociatedData, nonceOrAssociatedData.Length - 4, chunkIndex);\n    }\n\n    internal static int GetCipherChunkSize(byte[] lengthPrefix, int maxCipherChunkSize)\n    {\n        if (lengthPrefix.Length == 0)\n        {\n            throw new AbpException(\"The encrypted BLOB is corrupted or has an invalid format: missing terminal record!\");\n        }\n\n        if (lengthPrefix.Length < ChunkLengthPrefixSize)\n        {\n            throw new AbpException(\"The encrypted BLOB is corrupted or has an invalid format: truncated chunk!\");\n        }\n\n        var cipherChunkSize = ReadInt32BigEndian(lengthPrefix, 0);\n        if (cipherChunkSize < 0 || cipherChunkSize > maxCipherChunkSize)\n        {\n            throw new AbpException(\"The encrypted BLOB is corrupted or has an invalid format: invalid chunk length!\");\n        }\n\n        return cipherChunkSize;\n    }\n\n    internal static byte[]? ReadExactly(Stream stream, int count)\n    {\n        var buffer = ReadUpTo(stream, count);\n        return buffer.Length == count ? buffer : null;\n    }\n\n    internal static byte[] ReadUpTo(Stream stream, int count)","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobEncryptionCodec.cs#L513-L549","documentation":"GetCipherChunkSize requires at least ChunkLengthPrefixSize (4) bytes for the length prefix. Fewer than that means the chunk header was cut off mid-prefix — the stream ended partway through reading the length, so the chunk is truncated and cannot be parsed.","triggerScenarios":"Decrypting a BLOB where the cipher stream ends after 1–3 bytes of a length prefix instead of the full 4 (e.g. truncation in the middle of a chunk boundary).","commonSituations":"Truncated object in storage; partial download; byte-level corruption that altered boundaries; mismatched format version producing wrong offsets.","solutions":["Re-upload the BLOB from a known-good source.","Verify storage-level object integrity (checksums, ETag, content-length).","Check for storage-side corruption or replication lag serving a stale partial object.","Ensure the writer and reader use the same codec version and chunk format."],"exampleFix":"// before — reading from an unverified source\nusing var s = await provider.GetStreamAsync(name);\nvar plain = await DecryptAsync(s); // throws [89]\n\n// after — verify length first\nvar info = await provider.GetOrNullAsync(name);\nif (info == null || info.ContentLength < MinimumCipherLength)\n    throw new InvalidOperationException(\"corrupt or truncated blob\");","handlingStrategy":"try-catch","validationCode":"// Reject objects whose length cannot contain even one length prefix.\nvar info = await provider.GetOrNullAsync(name);\nif (info == null || info.ContentLength < 4 /* ChunkLengthPrefixSize */)\n    throw new InvalidOperationException($\"BLOB '{name}' is too short to contain a valid chunk header.\");","typeGuard":"public sealed record MinLengthBlob(string Name, long ContentLength)\n{\n    public static MinLengthBlob Check(string name, long len)\n    {\n        const int MinCipherLen = 16; // magic + at least a length prefix\n        if (len < MinCipherLen) throw new InvalidOperationException(\"blob too short\");\n        return new MinLengthBlob(name, len);\n    }\n}","tryCatchPattern":"try\n{\n    return await blob.GetAllBytesAsync(name);\n}\ncatch (AbpException ex) when (ex.Message.Contains(\"truncated chunk\"))\n{\n    logger.LogError(ex, \"BLOB '{Name}' truncated mid-header; re-upload.\", name);\n    throw;\n}","preventionTips":["Verify object content-length against expectations before decrypting.","Store ETag/checksums and validate them on read.","Re-upload truncated objects rather than retrying reads.","Match writer and reader codec versions."],"tags":["crypto","integrity","corruption","truncation"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}