gchq/CyberChef · error · OperationError
Invalid witness version: ${witnessVersion}. Must be 0-16.
Error message
Invalid witness version: ${witnessVersion}. Must be 0-16. What it means
Thrown by encode() in src/core/lib/Bech32.mjs:193 in SegWit mode (segwit=true, data.length>=2) when the first byte of data — interpreted as the witness version — exceeds 16. BIP-0173/BIP-0350 define witness versions 0 through 16 only; each version is a single 5-bit word, so values 17-255 are not representable and not defined by the protocol.
Source
Thrown at src/core/lib/Bech32.mjs:193
}
// Check HRP characters (ASCII 33-126)
for (let i = 0; i < hrp.length; i++) {
const c = hrp.charCodeAt(i);
if (c < 33 || c > 126) {
throw new OperationError(`HRP contains invalid character at position ${i}. Only printable ASCII characters (33-126) are allowed.`);
}
}
// Convert HRP to lowercase
const hrpLower = hrp.toLowerCase();
let words;
if (segwit && data.length >= 2) {
// SegWit encoding: first byte is witness version (0-16), rest is witness program
const witnessVersion = data[0];
if (witnessVersion > 16) {
throw new OperationError(`Invalid witness version: ${witnessVersion}. Must be 0-16.`);
}
const witnessProgram = Array.prototype.slice.call(data, 1);
// Validate witness program length per BIP-0141
if (witnessProgram.length < 2 || witnessProgram.length > 40) {
throw new OperationError(`Invalid witness program length: ${witnessProgram.length}. Must be 2-40 bytes.`);
}
if (witnessVersion === 0 && witnessProgram.length !== 20 && witnessProgram.length !== 32) {
throw new OperationError(`Invalid witness program length for v0: ${witnessProgram.length}. Must be 20 or 32 bytes.`);
}
// Witness version is kept as single 5-bit value, program is converted
words = [witnessVersion].concat(toWords(witnessProgram));
} else {
// Generic encoding: convert all bytes to 5-bit words
words = toWords(data);
}
View on GitHub (pinned to 4290ea7539)
Solutions
- Ensure data[0] is a witness version in 0..16 when segwit=true.
- If you do not mean SegWit, call encode with segwit=false (the default).
- Prepend the correct witness version byte, e.g. [0, ...witnessProgram] for v0.
- Validate before calling: if (segwit && (data[0] < 0 || data[0] > 16)) throw.
Example fix
// before - raw program passed without a witness version, or version > 16
encode('bc', programBytes, 'Bech32', true);
// after - prepend witness version 0
encode('bc', [0, ...programBytes], 'Bech32', true);
// or, for generic (non-SegWit) Bech32
encode('bc', programBytes, 'Bech32', false); Defensive patterns
Strategy: validation
Validate before calling
function validateSegwitPayload(data) {
if (!Array.isArray(data) || data.length < 2) throw new Error('SegWit payload too short');
if (data[0] < 0 || data[0] > 16) throw new RangeError(`witness version ${data[0]} out of range 0-16`);
return data;
} Type guard
function isValidSegwitVersion(b) {
return Number.isInteger(b) && b >= 0 && b <= 16;
} Try / catch
try {
encode('bc', data, 'Bech32', true);
} catch (e) {
if (e instanceof OperationError && /Invalid witness version/.test(e.message)) {
// data[0] is not a version; use segwit=false or prepend a real version
}
} Prevention
- Only set segwit=true when data[0] is genuinely a witness version 0-16.
- Keep witness version in a dedicated variable rather than reusing a data byte.
- For non-SegWit Bech32, call encode with segwit=false.
When it happens
Trigger: encode('bc', [17, ...program], 'Bech32', true), encode('bc', [255, ...], 'Bech32', true), or any segwit encode where data[0] > 16. Common when the caller did not actually intend SegWit but left segwit=true, so a raw data byte (e.g. 0x1c) becomes the 'witness version'.
Common situations: Passing a full raw payload as SegWit data without prepending a witness version; using segwit=true for a non-SegWit (generic) Bech32 use; witness version sourced from a byte that was actually data; protocol upgrade where the caller assumed a version > 16 exists.
Related errors
- Invalid witness program length for v0: ${witnessProgram.leng
- Invalid witness program length: ${witnessProgram.length}. Mu
- Invalid padding: too many bits remaining
- Encoded string exceeds maximum length of 90 characters (got
- Invalid Bech32 string: exceeds maximum length of 90 characte
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/819305abeaf2b217.
Report an issue: GitHub.