apache/shardingsphere · error · DecryptFailedException

Failed to decrypt the ciphertext '%s' in '%s'.

Error message

Failed to decrypt the ciphertext '%s' in '%s'.

What it means

EncryptMergedResult.getValue decrypts cipher values for encrypted columns on result merge. When EncryptColumn.getCipher().decrypt(...) throws any Exception, it is rethrown as DecryptFailedException with the ciphertext value, a database/table/column identifier, and the original cause. The rendered message is 'Failed to decrypt the ciphertext '%s' in '%s'.', where the second placeholder is the identifier string.

Source

Thrown at features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/merge/dql/EncryptMergedResult.java:77

        String originalTableName = columnSegmentBoundInfo.get().getOriginalTable().getValue();
        String originalColumnName = columnSegmentBoundInfo.get().getOriginalColumn().getValue();
        ShardingSphereDatabase database = metaData.containsDatabase(columnSegmentBoundInfo.get().getOriginalDatabase())
                ? metaData.getDatabase(columnSegmentBoundInfo.get().getOriginalDatabase())
                : this.database;
        Optional<EncryptRule> rule = database.getRuleMetaData().findSingleRule(EncryptRule.class);
        if (!rule.isPresent() || !rule.get().findEncryptTable(originalTableName).map(optional -> optional.isEncryptColumn(originalColumnName)).orElse(false)) {
            return getMergedResult().getValue(columnIndex, type);
        }
        Object cipherValue = getMergedResult().getValue(columnIndex, Object.class);
        EncryptColumn encryptColumn = rule.get().getEncryptTable(originalTableName).getEncryptColumn(originalColumnName);
        String schemaName = selectStatementContext.getTablesContext().getSchemaName()
                .orElseGet(() -> new DatabaseTypeRegistry(selectStatementContext.getSqlStatement().getDatabaseType()).getDefaultSchemaName(database.getName()));
        try {
            return encryptColumn.getCipher().decrypt(database.getName(), schemaName, originalTableName, originalColumnName, cipherValue);
            // CHECKSTYLE:OFF
        } catch (final Exception ex) {
            // CHECKSTYLE:ON
            throw new DecryptFailedException(String.valueOf(cipherValue), new SQLExceptionIdentifier(database.getName(), originalTableName, originalColumnName), ex);
        }
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Verify the encrypt key/algorithm in the ShardingSphere config matches what encrypted the stored data
  2. Check the cause chain: a padding/encoding error usually means wrong key; 'bad input length' or garbage output means algorithm mismatch
  3. Re-encrypt existing data with the current key (migration tooling or a one-off decrypt-with-old/encrypt-with-new pass)
  4. Restore corrupted rows from backup or mark them for re-initialization
Defensive patterns

Strategy: try-catch

Validate before calling

try { byte[] probe = cipher; /* decrypt one known row at startup */ algorithm.decrypt(probe); } catch (Exception e) { throw new IllegalStateException("Encrypt key does not match stored data", e); }

Try / catch

catch (DecryptFailedException e) { log.cipher(e.getCipherValue()); log.identifier(e.getIdentifier()); /* quarantine row, continue merging others */ }

Prevention

When it happens

Trigger: SELECTing an encrypted column whose stored data cannot be decrypted by the configured algorithm: wrong key in config, data encrypted with a different algorithm (migration/key rotation), corrupted ciphertext, or manually inserted plaintext in a cipher column.

Common situations: Key rotation without re-encrypting existing rows; copying a database between environments with different encrypt keys; switching algorithm names (AES to SM4 etc.) while keeping old data; DBAs writing raw values directly into cipher columns.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/4ff1216d05ffa551. Report an issue: GitHub.