abpframework/abp · error · AbpException

The encrypted BLOB is corrupted or has an invalid format: tr

Error message

The encrypted BLOB is corrupted or has an invalid format: truncated chunk!

What it means

DecryptPayload in ChunkedDecryptingReadStream reads the cipher chunk body and its GCM tag with ReadExactly. If either returns null (the cipher stream ended before the full chunk or tag arrived), the chunk is truncated and decryption cannot proceed, so it throws AbpException.

Source

Thrown at framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/ChunkedDecryptingReadStream.cs:106

                throw new AbpException("The encrypted BLOB is corrupted or has an invalid format: invalid terminal record!");
            }

            SetChunkIndex(_chunkIndex);
            BlobEncryptionCodec.VerifyTerminalRecordCore(_chunkCipher, _associatedData, _nonce, terminalTag);
            return null;
        }

        return DecryptPayload(
            await BlobEncryptionCodec.ReadExactlyAsync(_cipherStream, cipherChunkSize, cancellationToken),
            await BlobEncryptionCodec.ReadExactlyAsync(_cipherStream, BlobEncryptionCodec.GcmTagSize, cancellationToken)
        );
    }

    private byte[] DecryptPayload(byte[]? cipherChunk, byte[]? tag)
    {
        if (cipherChunk == null || tag == null)
        {
            throw new AbpException("The encrypted BLOB is corrupted or has an invalid format: truncated chunk!");
        }

        SetChunkIndex(_chunkIndex);
        var plainChunk = BlobEncryptionCodec.DecryptChunkCore(_chunkCipher, _associatedData, _nonce, cipherChunk, tag);
        _chunkIndex++;
        return plainChunk;
    }

    private void SetChunkIndex(int chunkIndex)
    {
        BlobEncryptionCodec.WriteChunkIndex(_nonce, chunkIndex);
        BlobEncryptionCodec.WriteChunkIndex(_associatedData, chunkIndex);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && !_disposed)
        {

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Re-upload or re-download the BLOB from a known-good source.
  2. Verify content-length/ETag on the stored object.
  3. Check the provider for partial-range or interrupted-stream behavior.
  4. Confirm writer and reader use the same chunk format/version.

Example fix

// before — accepting a short read
var n = await cipherStream.ReadAsync(buf, 0, buf.Length);
// proceed even if n < buf.Length -> truncated chunk -> throws [98]

// after — use the codec's exact readers, and validate object length up front
var meta = await provider.GetOrNullAsync(name);
if (meta?.ContentLength is long len && len < MinimumValidCipherLength)
    throw new InvalidOperationException("blob too short to be valid");
using var s = await provider.GetStreamAsync(name);
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the stored object is large enough to contain its advertised chunks.
var info = await provider.GetOrNullAsync(name);
if (info == null) throw new FileNotFoundException(name);
if (info.ContentLength < 32) // magic + header + at least one length prefix
    throw new InvalidOperationException($"BLOB '{name}' too short; likely truncated.");

Type guard

public sealed record VerifiedEncryptedBlob(string Name, long ContentLength)
{
    public static VerifiedEncryptedBlob Check(string name, long len)
    {
        if (len < 32) throw new InvalidOperationException("blob too short / truncated chunk");
        return new VerifiedEncryptedBlob(name, len);
    }
}

Try / catch

try
{
    return await blob.GetAllBytesAsync(name);
}
catch (AbpException ex) when (ex.Message.Contains("truncated chunk"))
{
    logger.LogError(ex, "BLOB '{Name}' truncated mid-chunk; re-upload.", name);
    throw;
}

Prevention

When it happens

Trigger: Decrypting a BLOB whose length prefix advertised a non-zero chunk but whose body or tag was cut short by the underlying stream ending early.

Common situations: Mid-chunk truncation in storage; interrupted downloads; storage corruption that altered boundaries; provider range-request returning fewer bytes than requested.

Related errors


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