{"record":{"id":"7373d2030d02dca2","repo":"gchq/CyberChef","slug":"invalid-witness-program-length-witnessprogram-l","errorCode":null,"errorMessage":"Invalid witness program length: ${witnessProgram.length}. Must be 2-40 bytes.","messagePattern":"Invalid witness program length: (.+?)\\. Must be 2-40 bytes\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Bech32.mjs","lineNumber":199,"sourceCode":"            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\n    // Create checksum\n    const checksum = createChecksum(hrpLower, words, encoding);\n\n    // Build result string\n    let result = hrpLower + \"1\";\n    for (const w of words.concat(checksum)) {","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Bech32.mjs#L181-L217","documentation":"Thrown by encode() in src/core/lib/Bech32.mjs:199 in SegWit mode when the witness program (data after the first byte) length is less than 2 or greater than 40 bytes. BIP-0141/BIP-0173 constrain witness programs to 2-40 bytes; outside this range the program cannot be a valid SegWit output and the address would be meaningless.","triggerScenarios":"encode('bc', [0, <1 byte>], 'Bech32', true) — program length 1 < 2. encode('bc', [0, ...41 bytes], 'Bech32', true) — length 41 > 40. Any segwit encode where data.slice(1).length is outside [2, 40].","commonSituations":"Truncated program (missing bytes during copy-paste); concatenating the wrong fields so the program is too short; using a 1-byte program by mistake; witness program from a buggy key derivation that produced an oversized output.","solutions":["Verify the witness program is a HASH160 (20 bytes) or SHA256 (32 bytes) for v0, or 2-40 bytes for v1+.","Re-derive the program from its source (e.g. HASH160 of the compressed pubkey for P2WPKH).","Confirm data[0] is the version and data.slice(1) is exactly the program — not the other way around.","If not building a SegWit address, use segwit=false."],"exampleFix":"// before - program too short\nencode('bc', [0, 0xab], 'Bech32', true);\n\n// after - 20-byte v0 program (P2WPKH)\nencode('bc', [0, ...hash160.slice(0, 20)], 'Bech32', true);","handlingStrategy":"validation","validationCode":"function validateWitnessProgram(program) {\n  if (!Array.isArray(program) || program.length < 2 || program.length > 40) {\n    throw new RangeError(`witness program length ${program ? program.length : 0} out of range 2-40`);\n  }\n  return program;\n}","typeGuard":"function isValidWitnessProgramLength(bytes) {\n  return Array.isArray(bytes) && bytes.length >= 2 && bytes.length <= 40;\n}","tryCatchPattern":"try {\n  encode('bc', [version, ...program], 'Bech32', true);\n} catch (e) {\n  if (e instanceof OperationError && /witness program length/.test(e.message)) {\n    // re-derive the program from its source hash\n  }\n}","preventionTips":["Derive programs from canonical hashes (HASH160 -> 20, SHA256 -> 32).","Confirm the byte array is exactly the program, with the version already split off.","Unit-test encoding with representative program lengths for each version."],"tags":["bech32","segwit","bitcoin","bip-0141","input-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}