gchq/CyberChef · error · OperationError

HRP contains invalid character at position ${i}. Only printa

Error message

HRP contains invalid character at position ${i}. Only printable ASCII characters (33-126) are allowed.

What it means

Thrown by encode() in src/core/lib/Bech32.mjs:181 when any character of the HRP falls outside ASCII range 33-126 (printable, excluding space). BIP-0173 restricts the HRP to ASCII 33-126; spaces, control characters, DEL, and any non-ASCII (UTF-8 multibyte) character are forbidden because they would break case-folding and checksum portability.

Source

Thrown at src/core/lib/Bech32.mjs:181

 * Encode data to Bech32/Bech32m string
 *
 * @param {string} hrp - Human-readable part
 * @param {number[]|Uint8Array} data - Data bytes to encode
 * @param {string} encoding - "Bech32" or "Bech32m"
 * @param {boolean} segwit - If true, treat first byte as witness version (for Bitcoin SegWit)
 * @returns {string} - Encoded Bech32/Bech32m string
 */
export function encode(hrp, data, encoding = "Bech32", segwit = false) {
    // Validate HRP
    if (!hrp || hrp.length === 0) {
        throw new OperationError("Human-Readable Part (HRP) cannot be empty.");
    }

    // 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.`);

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Trim whitespace and newlines from the HRP: hrp = hrp.trim().
  2. Restrict the HRP to the BIP-0173 character set before calling encode.
  3. Use a known-good HRP constant ('bc', 'tb', 'bcrt', 'ltc', etc.).
  4. If the HRP is user-supplied, validate each character is in 33-126 and surface a clear error.

Example fix

// before - trailing newline in config HRP
encode(hrp + '\n', program, 'Bech32', true);

// after - sanitize the HRP
const cleanHrp = hrp.replace(/[^\x21-\x7e]/g, '');
encode(cleanHrp, program, 'Bech32', true);
Defensive patterns

Strategy: validation

Validate before calling

function sanitizeHrp(hrp) {
  if (typeof hrp !== 'string') throw new TypeError('HRP must be a string');
  return hrp.replace(/[^\x21-\x7e]/g, '');
}

Type guard

function isValidHrp(hrp) {
  if (typeof hrp !== 'string' || hrp.length === 0) return false;
  for (let i = 0; i < hrp.length; i++) {
    const c = hrp.charCodeAt(i);
    if (c < 33 || c > 126) return false;
  }
  return true;
}

Try / catch

try {
  encode(hrp, data, 'Bech32', true);
} catch (e) {
  if (e instanceof OperationError && /HRP contains invalid character/.test(e.message)) {
    hrp = hrp.replace(/[^\x21-\x7e]/g, '');
  }
}

Prevention

When it happens

Trigger: encode('b c', data) (space, code 32 < 33), encode('b\u0000c', data) (null byte), encode('bérica', data) (non-ASCII), encode('bc\n', data) (trailing newline). Any HRP containing a character whose charCodeAt is < 33 or > 126.

Common situations: Trailing newline or whitespace in a config-supplied HRP; copy-paste of an HRP that included a space; using a localized/non-Latin HRP; accidentally passing the full address string as the HRP.

Understand the failure class

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/615227fc6dc3d697. Report an issue: GitHub.