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

  1. Re-upload the BLOB and ensure the upload completes fully.
  2. Verify the stored object's byte length against the expected ciphertext length.
  3. Check the storage backend for partial/interrupted writes and clean them up.
  4. 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

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


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/6d919278e667d936. Report an issue: GitHub.