gchq/CyberChef · error · OperationError

Invalid hexadecimal input. Length must be even.

Error message

Invalid hexadecimal input. Length must be even.

What it means

Thrown by Disassemble ARM run() when the hex string has an odd number of characters after whitespace removal. Each byte is two hex digits; an odd length means a half-byte is unpaired and cannot be parsed into a byte array. The check runs after the character-class check and after the empty-input early return.

Source

Thrown at src/core/operations/DisassembleARM.mjs:91

            startAddress,
            showHex,
            showPosition
        ] = args;

        // Remove whitespace from input
        const hexInput = input.replace(/\s/g, "");

        // Validate hex input
        if (!/^[0-9a-fA-F]*$/.test(hexInput)) {
            throw new OperationError("Invalid hexadecimal input. Please provide valid hex characters only.");
        }

        if (hexInput.length === 0) {
            return "";
        }

        if (hexInput.length % 2 !== 0) {
            throw new OperationError("Invalid hexadecimal input. Length must be even.");
        }

        // Convert hex string to byte array
        const bytes = [];
        for (let i = 0; i < hexInput.length; i += 2) {
            bytes.push(parseInt(hexInput.substr(i, 2), 16));
        }

        // Determine architecture constant
        let arch;
        if (architecture === "ARM64 (AArch64)") {
            arch = cs.ARCH_ARM64;
        } else {
            arch = cs.ARCH_ARM;
        }

        // Determine mode constant
        let modeValue = cs.MODE_LITTLE_ENDIAN;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Count the hex digits and pad/trim to an even length.
  2. If a leading nibble is missing, prepend '0' to the first byte (e.g. '1A3' -> '01A3').
  3. If the last nibble is spurious, drop it; if it is real, add its missing partner.
  4. Re-dump the bytes with a tool that emits two digits per byte.

Example fix

// before
input: "90 00 00 1"  // last byte missing a nibble -> odd length

// after
input: "90 00 00 14" // even length
Defensive patterns

Strategy: validation

Validate before calling

function isEvenLengthHex(s) {
    const h = String(s).replace(/\s/g, "");
    return /^[0-9a-fA-F]*$/.test(h) && h.length % 2 === 0;
}

Type guard

/** @returns {boolean} */
function isEvenLengthHexString(s) {
    const h = typeof s === "string" ? s.replace(/\s/g, "") : "";
    return /^[0-9a-fA-F]*$/.test(h) && h.length % 2 === 0;
}

Try / catch

try {
    out = disassembleArm.run(input, args);
} catch (e) {
    if (e instanceof OperationError && /Length must be even/.test(e.message)) {
        // pad leading 0 or trim a stray trailing nibble
    } else throw e;
}

Prevention

When it happens

Trigger: A hex string whose length % 2 != 0: a missing leading zero (e.g. '1A3' instead of '01A3' or '1A30'), a truncated copy-paste that drops one nibble, or a stray digit appended.

Common situations: Copy-paste truncation dropping the last nibble; dropping a leading '0' from the first byte; concatenating hex lines and losing a character at a join; OCR/typing error.

Related errors


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