gchq/CyberChef · error · OperationError

Encoded string exceeds maximum length of 90 characters (got

Error message

Encoded string exceeds maximum length of 90 characters (got ${result.length}). Consider using smaller input data.

What it means

Thrown by encode() in src/core/lib/Bech32.mjs:223 after building the result string if its total length exceeds 90 characters. BIP-0173 caps the entire Bech32 string (HRP + separator + data + checksum) at 90 characters; longer inputs would violate the specification and risk incompatibility across parsers. This is a final guard, checked after the checksum is appended.

Source

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

        // 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);
    }

    // Create checksum
    const checksum = createChecksum(hrpLower, words, encoding);

    // Build result string
    let result = hrpLower + "1";
    for (const w of words.concat(checksum)) {
        result += CHARSET[w];
    }

    // Check maximum length (90 characters)
    if (result.length > 90) {
        throw new OperationError(`Encoded string exceeds maximum length of 90 characters (got ${result.length}). Consider using smaller input data.`);
    }

    return result;
}

/**
 * Decode a Bech32/Bech32m string
 *
 * @param {string} str - Bech32/Bech32m encoded string
 * @param {string} encoding - "Bech32", "Bech32m", or "Auto-detect"
 * @returns {{hrp: string, data: number[]}} - Decoded HRP and data bytes
 */
export function decode(str, encoding = "Auto-detect") {
    // Check for empty input
    if (!str || str.length === 0) {
        throw new OperationError("Input cannot be empty.");
    }

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Reduce the input data length so the final string is <= 90 characters.
  2. Use a shorter HRP.
  3. Split large payloads across multiple Bech32 strings if the use case allows.
  4. If you need arbitrary-length Base32-like encoding without the 90-char cap, use a different scheme (e.g. raw Base32).

Example fix

// before - payload too large for one Bech32 string
encode('bb', hugeByteArray, 'Bech32', false);

// after - chunk the payload
const chunks = chunkBytes(hugeByteArray, maxBytesForLimit);
const encoded = chunks.map(c => encode('bb', c, 'Bech32', false));
Defensive patterns

Strategy: validation

Validate before calling

function estimateBech32Length(hrp, dataLen, segwit) {
  const programLen = segwit ? dataLen - 1 : dataLen;
  const wordCount = Math.ceil((programLen * 8) / 5) + (segwit ? 1 : 0);
  return hrp.length + 1 + wordCount + 6;
}
// if (estimateBech32Length(hrp, data.length, true) > 90) reject early;

Type guard

function fitsBech32Limit(hrp, data, segwit) {
  return estimateBech32Length(hrp, data.length, segwit) <= 90;
}

Try / catch

try {
  encode(hrp, data, 'Bech32', segwit);
} catch (e) {
  if (e instanceof OperationError && /exceeds maximum length of 90/.test(e.message)) {
    // split payload or shorten HRP
  }
}

Prevention

When it happens

Trigger: encode(hrp, largeData, ...) where hrp.length + 1 + ceil(data.length*8/5) + 6 > 90. For example, a long HRP combined with a 40-byte program, or generic (non-segwit) encoding of a >50-byte payload.

Common situations: Encoding arbitrary large data (not a Bitcoin address) into Bech32 and hitting the spec limit; very long HRP chosen by the caller; trying to embed a full transaction or message in a single Bech32 string instead of chunking.

Related errors


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