gchq/CyberChef · error · OperationError
Invalid Bech32 string: mixed case is not allowed. Use all up
Error message
Invalid Bech32 string: mixed case is not allowed. Use all uppercase or all lowercase.
What it means
Thrown by decode() in src/core/lib/Bech32.mjs:251 when the input contains both uppercase (A-Z) and lowercase (a-z) letters. BIP-0173 forbids mixed case: a Bech32 string must be entirely uppercase or entirely lowercase so that case-insensitive comparison is unambiguous. The check uses /[A-Z]/ and /[a-z]/ regexes; if both match, the string is invalid regardless of correctness.
Source
Thrown at src/core/lib/Bech32.mjs:251
* @param {string} encoding - "Bech32", "Bech32m", or "Auto-detect"
* @returns {{hrp: string, data: number[]}} - Decoded HRP and data bytes
*/
export function decode(str, encoding = "Auto-detect") {
// Check for empty input
if (!str || str.length === 0) {
throw new OperationError("Input cannot be empty.");
}
// Check maximum length
if (str.length > 90) {
throw new OperationError(`Invalid Bech32 string: exceeds maximum length of 90 characters (got ${str.length}).`);
}
// Check for mixed case
const hasUpper = /[A-Z]/.test(str);
const hasLower = /[a-z]/.test(str);
if (hasUpper && hasLower) {
throw new OperationError("Invalid Bech32 string: mixed case is not allowed. Use all uppercase or all lowercase.");
}
// Convert to lowercase for processing
str = str.toLowerCase();
// Find separator (last occurrence of '1')
const sepIndex = str.lastIndexOf("1");
if (sepIndex === -1) {
throw new OperationError("Invalid Bech32 string: no separator '1' found.");
}
if (sepIndex === 0) {
throw new OperationError("Invalid Bech32 string: Human-Readable Part (HRP) cannot be empty.");
}
if (sepIndex + 7 > str.length) {
throw new OperationError("Invalid Bech32 string: data part is too short (minimum 6 characters for checksum).");
}View on GitHub (pinned to 4290ea7539)
Solutions
- Normalize the whole string to one case before decoding: str.toLowerCase() or str.toUpperCase().
- Disable auto-capitalization on input fields that accept addresses.
- Validate case consistency before submitting and warn the user.
- If normalizing changes the address, treat it as the canonical form (Bech32 case is not semantically significant).
Example fix
// before - mixed case decode(userInput); // 'Bc1QAb...' // after - normalize to lowercase decode(userInput.toLowerCase());
Defensive patterns
Strategy: validation
Validate before calling
function normalizeBech32Case(str) {
const hasUpper = /[A-Z]/.test(str);
const hasLower = /[a-z]/.test(str);
if (hasUpper && hasLower) return str.toLowerCase(); // or toUpperCase
return str;
} Type guard
function isSingleCase(s) {
return typeof s === 'string' && !(/[A-Z]/.test(s) && /[a-z]/.test(s));
} Try / catch
try {
decode(input);
} catch (e) {
if (e instanceof OperationError && /mixed case/.test(e.message)) {
input = input.toLowerCase(); // canonical fix
}
} Prevention
- Normalize the whole address to one case before decoding.
- Disable auto-capitalize on address input fields.
- Warn users not to partially edit address case.
When it happens
Trigger: decode('bc1qABcDeFgH...') where some letters are upper and some lower. Happens when auto-correct or a title-case formatter touched the address, or when an uppercase address was partially lowercased.
Common situations: Mobile keyboards auto-capitalizing the first letter; copy-paste through a tool that title-cased the string; user manually edited part of the address; QR-code decoders that normalize case inconsistently.
Related errors
- Invalid padding: too many bits remaining
- Invalid Bech32 string: exceeds maximum length of 90 characte
- Invalid padding: non-zero bits in padding
- Invalid witness version: ${witnessVersion}. Must be 0-16.
- Invalid witness program length for v0: ${witnessProgram.leng
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/1ce0bb156779f72d.
Report an issue: GitHub.