abpframework/abp · critical · AbpException
The data is too large: the maximum chunk count has been exce
Error message
The data is too large: the maximum chunk count has been exceeded!
What it means
The per-BLOB nonce is an 8-byte random base plus a 4-byte chunk index. If the index becomes negative (i.e. it has overflowed the signed 32-bit range), the same nonce would repeat for the same key, which catastrophically breaks AES-GCM confidentiality. CreateChunkNonce refuses to build such a nonce and throws AbpException.
Source
Thrown at framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobEncryptionCodec.cs:477
internal static void VerifyTerminalRecordCore(IDisposable cipher, byte[] associatedData, byte[] nonce, byte[] tag)
{
#if NETSTANDARD2_0
throw new PlatformNotSupportedException("AES-GCM is not available on .NET Standard 2.0!");
#else
// Throws CryptographicException if the tag is invalid.
((AesGcm)cipher).Decrypt(nonce, Array.Empty<byte>(), tag, Array.Empty<byte>(), associatedData);
#endif
}
// Nonce = 8-byte random base + 4-byte chunk index; the per-BLOB key (random salt)
// makes cross-BLOB reuse harmless and the index keeps it unique within the BLOB.
internal static byte[] CreateChunkNonce(byte[] baseNonce, 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!");
}
var nonce = new byte[GcmNonceSize];
Array.Copy(baseNonce, 0, nonce, 0, BaseNonceSize);
WriteInt32BigEndian(nonce, BaseNonceSize, chunkIndex);
return nonce;
}
internal static byte[] CreateChunkAssociatedData(byte[] associatedDataPrefix, int chunkIndex)
{
var associatedData = new byte[associatedDataPrefix.Length + 4];
Array.Copy(associatedDataPrefix, 0, associatedData, 0, associatedDataPrefix.Length);
WriteInt32BigEndian(associatedData, associatedDataPrefix.Length, chunkIndex);
return associatedData;
}
// A stream builds one nonce and one associated-data buffer with these, then rewrites only
// the trailing chunk index per chunk with WriteChunkIndex; both hold the index as theirView on GitHub (pinned to 7ed43b1931)
Solutions
- Increase the configured chunk size so the content fits within int.MaxValue chunks.
- Split the content into multiple BLOBs each under the chunk-count ceiling.
- Cap upload size at the application layer based on chunkSize * int.MaxValue.
- Audit chunkSize configuration — it should be in the multi-MB range, not KB.
Example fix
// before
Configure<AbpBlobStoringEncryptionOptions>(o =>
{
o.ChunkSize = 1024; // 1 KB -> overflows at ~2 TB
});
// after
Configure<AbpBlobStoringEncryptionOptions>(o =>
{
o.ChunkSize = 4 * 1024 * 1024; // 4 MB -> overflows at ~8 PB
}); Defensive patterns
Strategy: validation
Validate before calling
// Compute the maximum content size for a chunk size and refuse oversized uploads.
static readonly long MaxEncryptedContentBytes =
(long)AbpBlobStoringEncryptionOptions.DefaultChunkSize * int.MaxValue;
static void AssertSize(long contentLength, int chunkSize)
{
var max = (long)chunkSize * int.MaxValue;
if (contentLength > max)
throw new InvalidOperationException(
$"Content ({contentLength} B) exceeds the encrypted-BLOB limit ({max} B) for chunkSize={chunkSize}.");
} Type guard
// Validate chunk size at configuration time.
public sealed record ChunkSize
{
public int Value { get; }
public ChunkSize(int bytes)
{
if (bytes < 1024 || bytes > 64 * 1024 * 1024)
throw new ArgumentOutOfRangeException(nameof(bytes), "Use a chunk size between 1 KB and 64 MB.");
Value = bytes;
}
} Try / catch
try
{
await blob.SaveAsync(name, bigStream);
}
catch (AbpException ex) when (ex.Message.Contains("maximum chunk count has been exceeded"))
{
// Not retryable as-is: the content is too large for the configured chunk size.
logger.LogError(ex, "Increase ChunkSize or split the content before retrying.");
throw;
} Prevention
- Set ChunkSize to multi-MB (e.g. 4–8 MB) so the int32 chunk ceiling is many PB, not TB.
- Enforce an upload-size cap derived from chunkSize * int.MaxValue at the API boundary.
- Audit chunkSize in configuration reviews.
- Split very large content into multiple BLOBs.
When it happens
Trigger: Streaming content whose chunk count exceeds int.MaxValue (~2.1 billion chunks) through the encrypting path, so CreateChunkNonce is called with a wrapped (negative) chunkIndex.
Common situations: A very small configured chunk size combined with extremely large content (e.g. 1 KB chunk size on multi-TB BLOBs); a runaway/miscalibrated producer feeding a tiny chunkSize.
Related errors
- The content is too large for the encrypted BLOB format (chun
- AES-GCM is not available on .NET Standard 2.0!
- code length overflow. (${buffer.getLengthInBits()}>${totalDa
- Too long data
- The BLOB encryption passphrase contains invalid characters (
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/e1875f9cdde2dcd2.
Report an issue: GitHub.