{"record":{"id":"27499749651d76e4","repo":"gchq/CyberChef","slug":"invalid-bech32-string-human-readable-part-hrp-c","errorCode":null,"errorMessage":"Invalid Bech32 string: Human-Readable Part (HRP) cannot be empty.","messagePattern":"Invalid Bech32 string: Human-Readable Part \\(HRP\\) cannot be empty\\.","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/lib/Bech32.mjs","lineNumber":264,"sourceCode":"\n    // Check for mixed case\n    const hasUpper = /[A-Z]/.test(str);\n    const hasLower = /[a-z]/.test(str);\n    if (hasUpper && hasLower) {\n        throw new OperationError(\"Invalid Bech32 string: mixed case is not allowed. Use all uppercase or all lowercase.\");\n    }\n\n    // Convert to lowercase for processing\n    str = str.toLowerCase();\n\n    // Find separator (last occurrence of '1')\n    const sepIndex = str.lastIndexOf(\"1\");\n    if (sepIndex === -1) {\n        throw new OperationError(\"Invalid Bech32 string: no separator '1' found.\");\n    }\n\n    if (sepIndex === 0) {\n        throw new OperationError(\"Invalid Bech32 string: Human-Readable Part (HRP) cannot be empty.\");\n    }\n\n    if (sepIndex + 7 > str.length) {\n        throw new OperationError(\"Invalid Bech32 string: data part is too short (minimum 6 characters for checksum).\");\n    }\n\n    // Extract HRP and data part\n    const hrp = str.substring(0, sepIndex);\n    const dataPart = str.substring(sepIndex + 1);\n\n    // Validate HRP characters\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}.`);\n        }\n    }\n","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/lib/Bech32.mjs#L246-L282","documentation":"Thrown by decode() in src/core/lib/Bech32.mjs:264 when the rightmost '1' separator is at index 0 — meaning nothing precedes it and the HRP is empty. This is the decode-side counterpart of the encode-side empty-HRP guard; an empty HRP makes checksum verification meaningless because the HRP contributes to polymod via hrpExpand.","triggerScenarios":"decode('1qwerty...') where the string starts with '1'. Reached after the separator is found (sepIndex !== -1) but equals zero. Happens when the HRP was stripped, leaving the separator as the first character.","commonSituations":"User pasted only the data+checksum part without the HRP; a regex or formatter deleted the HRP prefix; an address from a chain whose HRP the user removed expecting it to be implicit; confused variable holding dataPart instead of the full string.","solutions":["Pass the complete Bech32 string including its HRP prefix (e.g. 'bc1q...').","If the HRP was stripped, re-prepend the correct HRP and '1' before decoding.","Validate that the string starts with a known HRP ('bc', 'tb', 'bcrt', etc.) before decoding.","Audit any pre-processing that might have truncated the prefix."],"exampleFix":"// before - HRP stripped, separator at index 0\ndecode('1qwl3q4l');\n\n// after - include the HRP\ndecode('bc1qwl3q4l...');","handlingStrategy":"validation","validationCode":"function requireHrpPrefix(str) {\n  const sep = str.lastIndexOf('1');\n  if (sep <= 0) throw new Error('Bech32 string missing HRP before separator');\n  return str;\n}","typeGuard":"function hasNonEmptyHrpBeforeSeparator(s) {\n  const i = typeof s === 'string' ? s.lastIndexOf('1') : -1;\n  return i > 0;\n}","tryCatchPattern":"try {\n  decode(input);\n} catch (e) {\n  if (e instanceof OperationError && /HRP.*cannot be empty/.test(e.message)) {\n    // re-prepend the correct HRP + '1'\n  }\n}","preventionTips":["Always pass the full address including its HRP prefix.","Validate the string starts with a known HRP ('bc', 'tb', 'bcrt', ...).","Avoid pre-processing that could strip the prefix."],"tags":["bech32","decoding","hrp","separator","input-validation"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}