apache/pulsar · error · IllegalArgumentException
Target buffer size is too small
Error message
Target buffer size is too small
What it means
MessageCryptoBc.decryptData computes cipher.getOutputSize(payload.remaining()) for AES-GCM decryption and requires the caller-provided targetBuffer to have that much remaining space; otherwise it throws IllegalArgumentException before attempting the doFinal. The plaintext is generally smaller than the ciphertext but the library reserves worst-case output size.
Source
Thrown at pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java:596
}
}
private boolean decryptData(SecretKey dataKeySecret, MessageMetadata msgMetadata,
ByteBuffer payload, ByteBuffer targetBuffer) {
// unpack iv and encrypted data
byte[] iv = msgMetadata.getEncryptionParam();
GCMParameterSpec gcmParams = new GCMParameterSpec(tagLen, iv);
try {
// mark the buffers to allow resetting them in case of decryption failure
payload.mark();
targetBuffer.mark();
Cipher cipher = getAesGcmCipher();
cipher.init(Cipher.DECRYPT_MODE, dataKeySecret, gcmParams);
int maxLength = cipher.getOutputSize(payload.remaining());
if (targetBuffer.remaining() < maxLength) {
throw new IllegalArgumentException("Target buffer size is too small");
}
int decryptedSize = cipher.doFinal(payload, targetBuffer);
targetBuffer.flip();
targetBuffer.limit(decryptedSize);
return true;
} catch (Exception e) {
// reset the buffers so that decryption can be retried with the same buffers
payload.reset();
targetBuffer.reset();
log.error().attr("logCtx", logCtx).exceptionMessage(e)
.log("Failed to decrypt message");
return false;
}
}
@Override
public int getMaxOutputSize(int inputLen) {View on GitHub (pinned to 820761864e)
Solutions
- Allocate the target buffer with headroom equal to or greater than cipher.getOutputSize(encryptedLength) (i.e. at least the ciphertext size plus tag)
- Clear/flip the target buffer before reuse so remaining() is maximal
- If you control the call site, mirror the encrypt-side sizing logic (payload + 16-byte GCM tag)
- Check that chunked-message reassembly is passing the correct per-chunk buffer rather than a fixed undersized one
Example fix
// before ByteBuffer target = ByteBuffer.allocate(encryptedChunk.remaining()); // after ByteBuffer target = ByteBuffer.allocate(encryptedChunk.remaining() + 16); // worst-case GCM output
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the decrypt target buffer can hold worst-case output
int needed = cipher.getOutputSize(encryptedChunk.remaining()); // at least encrypted size + tag
if (targetBuffer.remaining() < needed) {
targetBuffer = ByteBuffer.allocate(needed);
} Try / catch
try {
boolean ok = crypto.decrypt(dataKeyInfo, encryptedPayload, targetBuffer);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Target buffer")) {
// reallocate with headroom and retry once
targetBuffer = ByteBuffer.allocate(encryptedPayload.remaining() + 16);
} else {
throw e;
}
} Prevention
- Size consumer decrypt buffers from the encrypted chunk length, not the expected plaintext length
- Clear/flip reusable buffers before each decrypt call
- Account for the 16-byte GCM tag in all buffer sizing math
- Cover buffer sizing with tests using the largest configured message size
When it happens
Trigger: Calling MessageCryptoBc.decrypt where the targetBuffer (the output buffer holding the decrypted payload) has remaining() fewer bytes than cipher.getOutputSize(payload.remaining()) for the encrypted chunk being decrypted.
Common situations: Consumer allocating a receive buffer exactly equal to the ciphertext length; reusing a buffer across messages where a later message's encrypted chunk is larger; custom decryption flows that pass undersized buffers instead of using the library's default handling.
Related errors
- Outbuffer has not enough space available
- Failed to decode private key
- Failed to decode public key
- The ${alg.name()} algorithm does not support Key Pairs.
- Illegal base64 character or Key file ${keyConfUrl} doesn't e
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/67edc1ee98949a2b.
Report an issue: GitHub.