{"record":{"id":"819305abeaf2b217","repo":"gchq/CyberChef","slug":"invalid-witness-version-witnessversion-must-b","errorCode":null,"errorMessage":"Invalid witness version: ${witnessVersion}. Must be 0-16.","messagePattern":"Invalid witness version: (.+?)\\. Must be 0-16\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Bech32.mjs","lineNumber":193,"sourceCode":"    }\n\n    // Check HRP characters (ASCII 33-126)\n    for (let i = 0; i < hrp.length; i++) {\n        const c = hrp.charCodeAt(i);\n        if (c < 33 || c > 126) {\n            throw new OperationError(`HRP contains invalid character at position ${i}. Only printable ASCII characters (33-126) are allowed.`);\n        }\n    }\n\n    // Convert HRP to lowercase\n    const hrpLower = hrp.toLowerCase();\n\n    let words;\n    if (segwit && data.length >= 2) {\n        // SegWit encoding: first byte is witness version (0-16), rest is witness program\n        const witnessVersion = data[0];\n        if (witnessVersion > 16) {\n            throw new OperationError(`Invalid witness version: ${witnessVersion}. Must be 0-16.`);\n        }\n        const witnessProgram = Array.prototype.slice.call(data, 1);\n\n        // Validate witness program length per BIP-0141\n        if (witnessProgram.length < 2 || witnessProgram.length > 40) {\n            throw new OperationError(`Invalid witness program length: ${witnessProgram.length}. Must be 2-40 bytes.`);\n        }\n        if (witnessVersion === 0 && witnessProgram.length !== 20 && witnessProgram.length !== 32) {\n            throw new OperationError(`Invalid witness program length for v0: ${witnessProgram.length}. Must be 20 or 32 bytes.`);\n        }\n\n        // Witness version is kept as single 5-bit value, program is converted\n        words = [witnessVersion].concat(toWords(witnessProgram));\n    } else {\n        // Generic encoding: convert all bytes to 5-bit words\n        words = toWords(data);\n    }\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Bech32.mjs#L175-L211","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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."],"exampleFix":"// before - raw program passed without a witness version, or version > 16\nencode('bc', programBytes, 'Bech32', true);\n\n// after - prepend witness version 0\nencode('bc', [0, ...programBytes], 'Bech32', true);\n// or, for generic (non-SegWit) Bech32\nencode('bc', programBytes, 'Bech32', false);","handlingStrategy":"validation","validationCode":"function validateSegwitPayload(data) {\n  if (!Array.isArray(data) || data.length < 2) throw new Error('SegWit payload too short');\n  if (data[0] < 0 || data[0] > 16) throw new RangeError(`witness version ${data[0]} out of range 0-16`);\n  return data;\n}","typeGuard":"function isValidSegwitVersion(b) {\n  return Number.isInteger(b) && b >= 0 && b <= 16;\n}","tryCatchPattern":"try {\n  encode('bc', data, 'Bech32', true);\n} catch (e) {\n  if (e instanceof OperationError && /Invalid witness version/.test(e.message)) {\n    // data[0] is not a version; use segwit=false or prepend a real version\n  }\n}","preventionTips":["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."],"tags":["bech32","segwit","bitcoin","bip-0173","input-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}