abpframework/abp · error · AbpException
The encrypted BLOB is corrupted or has an invalid format: mi
Error message
The encrypted BLOB is corrupted or has an invalid format: missing terminal record!
What it means
GetCipherChunkSize reads the 4-byte length prefix of the next record. A zero-length prefix (EOF) where a terminal record was expected means the BLOB ended without its authenticated terminal record, so completeness cannot be verified. The codec throws rather than treat a truncated stream as complete.
Source
Thrown at framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobEncryptionCodec.cs:526
return associatedData;
}
internal static void WriteChunkIndex(byte[] nonceOrAssociatedData, int chunkIndex)
{
if (chunkIndex < 0)
{
// A wrapped chunk index would repeat a nonce for the same key, which breaks AES-GCM.
throw new AbpException("The data is too large: the maximum chunk count has been exceeded!");
}
WriteInt32BigEndian(nonceOrAssociatedData, nonceOrAssociatedData.Length - 4, chunkIndex);
}
internal static int GetCipherChunkSize(byte[] lengthPrefix, int maxCipherChunkSize)
{
if (lengthPrefix.Length == 0)
{
throw new AbpException("The encrypted BLOB is corrupted or has an invalid format: missing terminal record!");
}
if (lengthPrefix.Length < ChunkLengthPrefixSize)
{
throw new AbpException("The encrypted BLOB is corrupted or has an invalid format: truncated chunk!");
}
var cipherChunkSize = ReadInt32BigEndian(lengthPrefix, 0);
if (cipherChunkSize < 0 || cipherChunkSize > maxCipherChunkSize)
{
throw new AbpException("The encrypted BLOB is corrupted or has an invalid format: invalid chunk length!");
}
return cipherChunkSize;
}
internal static byte[]? ReadExactly(Stream stream, int count)
{View on GitHub (pinned to 7ed43b1931)
Solutions
- Re-upload the BLOB and ensure the upload completes fully.
- Verify the stored object's byte length against the expected ciphertext length.
- Check the storage backend for partial/interrupted writes and clean them up.
- Confirm the BLOB was written by a compatible version of the encryption codec.
Example fix
// before — swallowing storage errors and proceeding
try { await blob.SaveAsync(name, data); } catch { /* ignored */ }
var read = await blob.GetAllBytesAsync(name); // throws [88]
// after — ensure the write actually completes
await blob.SaveAsync(name, data);
var stat = await provider.GetOrNullAsync(name);
if (stat == null) throw new InvalidOperationException("upload lost"); Defensive patterns
Strategy: try-catch
Validate before calling
// Verify object presence and minimum length before decrypting.
var info = await provider.GetOrNullAsync(name);
if (info == null)
throw new FileNotFoundException($"BLOB '{name}' not found.");
if (info.ContentLength < Magic.Length /* magic header */)
throw new InvalidOperationException($"BLOB '{name}' is too short to be a valid encrypted container."); Type guard
public sealed record VerifiedEncryptedBlob(string Name, long ContentLength)
{
public static VerifiedEncryptedBlob Check(string name, long len)
{
if (len < 16) throw new InvalidOperationException("blob too short to be a valid encrypted container");
return new VerifiedEncryptedBlob(name, len);
}
} Try / catch
try
{
return await blob.GetAllBytesAsync(name);
}
catch (AbpException ex) when (ex.Message.Contains("missing terminal record"))
{
logger.LogError(ex, "BLOB '{Name}' is truncated; re-upload from a known-good source.", name);
// Surface to caller; do not retry the same corrupted object.
throw;
} Prevention
- Ensure uploads complete fully (verify status/ETag) before reads.
- Store and compare a checksum alongside each BLOB.
- Clean up partial/interrupted multipart uploads in storage.
- Confirm writer and reader use the same codec version.
When it happens
Trigger: Decrypting a BLOB whose cipher stream returns zero bytes for the length-prefix read because the data was truncated before the terminal record, or the underlying stream is empty/incomplete.
Common situations: A truncated upload (network drop, partial write, interrupted multipart upload); corrupted/empty object in storage; wrong format version; storage provider returned a partial object.
Related errors
- The encrypted BLOB is corrupted or has an invalid format: tr
- The encrypted BLOB is corrupted or has an invalid format: tr
- The encrypted BLOB is corrupted or has an invalid format: in
- The encrypted BLOB is corrupted or has an invalid format: in
- The stream can not be read anymore, because a previous read
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/6d919278e667d936.
Report an issue: GitHub.