{"record":{"id":"799bf1f8b44a1024","repo":"apache/cassandra","slug":"failed-to-encrypt-commit-log-block","errorCode":null,"errorMessage":"failed to encrypt commit log block","messagePattern":"failed to encrypt commit log block","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/security/EncryptionUtils.java","lineNumber":110,"sourceCode":"        final int plainTextLength = inputBuffer.remaining();\n        final int encryptLength = cipher.getOutputSize(plainTextLength);\n        ByteBuffer outputBuffer = inputBuffer.duplicate();\n        outputBuffer = ByteBufferUtil.ensureCapacity(outputBuffer, encryptLength, allowBufferResize);\n\n        // it's unfortunate that we need to allocate a small buffer here just for the headers, but if we reuse the input buffer\n        // for the output, then we would overwrite the first n bytes of the real data with the header data.\n        ByteBuffer intBuf = ByteBuffer.allocate(ENCRYPTED_BLOCK_HEADER_SIZE);\n        intBuf.putInt(0, encryptLength);\n        intBuf.putInt(4, plainTextLength);\n        channel.write(intBuf);\n\n        try\n        {\n            cipher.doFinal(inputBuffer, outputBuffer);\n        }\n        catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e)\n        {\n            throw new IOException(\"failed to encrypt commit log block\", e);\n        }\n\n        outputBuffer.position(0).limit(encryptLength);\n        channel.write(outputBuffer);\n        outputBuffer.position(0).limit(encryptLength);\n\n        return outputBuffer;\n    }\n\n    public static ByteBuffer encrypt(ByteBuffer inputBuffer, ByteBuffer outputBuffer, boolean allowBufferResize, Cipher cipher) throws IOException\n    {\n        Preconditions.checkNotNull(outputBuffer, \"output buffer may not be null\");\n        return encryptAndWrite(inputBuffer, new ChannelAdapter(outputBuffer), allowBufferResize, cipher);\n    }\n\n    /**\n     * Decrypt the input data, as well as manage sizing of the {@code outputBuffer}; if the buffer is not big enough,\n     * deallocate current, and allocate a large enough buffer.","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/security/EncryptionUtils.java#L92-L128","documentation":"EncryptionUtils.encryptAndWrite finishes the JCE encryption of a commit log block with cipher.doFinal. If the cipher throws (output buffer too small, block size problems, bad padding state), it is wrapped in IOException(\"failed to encrypt commit log block\").","triggerScenarios":"encrypt -> encryptAndWrite with an outputBuffer smaller than the cipher's required output size, or a cipher whose doFinal fails mid-block (e.g. uninitialized cipher, wrong key state).","commonSituations":"Bug-level buffer sizing mismatches between compressed plaintext length and encrypted output capacity, or a JCE provider behaving differently than expected after a JDK upgrade.","solutions":["Check the wrapped JCE exception: ShortBufferException means enlarge outputBuffer (header + input length padding per cipher).","Verify the cipher returned by CipherFactory.getEncryptor was initialized with a valid key and IV.","Confirm the JDK/JCE provider is consistent with the configured transformation; update the transformation if the provider changed.","If reproducible, report/inspect buffer sizing logic in EncryptionUtils against the configured cipher's block size."],"exampleFix":"// before: output buffer too small\nByteBuffer out = ByteBuffer.allocate(input.remaining());\n// after: leave room for block padding + IV overhead\nByteBuffer out = ByteBuffer.allocate(input.remaining() + cipher.getBlockSize());","handlingStrategy":"try-catch","validationCode":"int needed = inputBuffer.remaining() + cipher.getBlockSize();\nif (outputBuffer.capacity() < needed) throw new IllegalArgumentException(\"output buffer too small for encryption: need \" + needed);","typeGuard":null,"tryCatchPattern":"try {\n    EncryptionUtils.encryptAndWrite(cipher, inputBuffer, false, channel);\n} catch (IOException e) {\n    if (e.getMessage().equals(\"failed to encrypt commit log block\")) {\n        // inspect e.getCause(): ShortBufferException -> enlarge buffer\n    }\n}","preventionTips":["Size output buffers with cipher block-size headroom","Use the CipherFactory-managed ciphers (thread-local cached, correctly initialized)","Run JDK upgrade tests for the encryption path"],"tags":["encryption","commitlog","buffer"],"backgroundTag":"encryption-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}