gchq/CyberChef · error · OperationError
Incorrectly Encoded Word
Error message
Incorrectly Encoded Word
What it means
Thrown by the MIME Decoding operation while parsing a Q-encoded encoded word, when a '=' escape appears too close to the end of the word to contain the required two hex digits. RFC 2047 Q-encoding uses '=XX' for a byte value; if the '=' is at a position where fewer than two characters follow it (i + 2 >= length), parseQEncodedWord throws at MIMEDecoding.mjs:152. This indicates a truncated or malformed escape sequence.
Source
Thrown at src/core/operations/MIMEDecoding.mjs:152
}
}
throw new OperationError("Unhandled Charset");
}
/**
* Parses a Q encoded word
*
* @param encodedWord
*/
parseQEncodedWord(encodedWord) {
let decodedWord = "";
for (let i = 0; i < encodedWord.length; i++) {
if (encodedWord[i] === "_") {
decodedWord += " ";
// Parse hex encoding
} else if (encodedWord[i] === "=") {
if ((i + 2) >= encodedWord.length) throw new OperationError("Incorrectly Encoded Word");
const decodedHex = Utils.byteArrayToChars(fromHex(encodedWord.substring(i + 1, i + 3)));
decodedWord += decodedHex;
i += 2;
} else if (
(encodedWord[i].charCodeAt(0) >= " ".charCodeAt(0) && encodedWord[i].charCodeAt(0) <= "~".charCodeAt(0)) ||
encodedWord[i] === "\n" ||
encodedWord[i] === "\r" ||
encodedWord[i] === "\t") {
decodedWord += encodedWord[i];
} else {
throw new OperationError("Incorrectly Encoded Word");
}
}
return decodedWord;
}
}
View on GitHub (pinned to 4290ea7539)
Solutions
- Repair the encoded word so every '=' is followed by exactly two hexadecimal digits (e.g. complete '=2' to '=20', remove a stray trailing '=').
- If the header is corrupt beyond repair, strip or replace the malformed encoded word before decoding.
- Re-acquire the original message from the source to avoid transport truncation.
Example fix
// before — dangling '=' (incomplete hex escape) // =?UTF-8?Q?Hello= world?= // after — complete the escape (=20 is space) // =?UTF-8?Q?Hello=20world?=
Defensive patterns
Strategy: validation
Validate before calling
// Reject Q-words with a dangling '=' escape before decoding.
function wellFormedQWord(w) {
for (let i = 0; i < w.length; i++) {
if (w[i] === '=' && i + 2 >= w.length) return false;
}
return true;
}
if (!wellFormedQWord(text)) {
// repair: pad/complete the escape, or strip the malformed word
} Type guard
function isWellFormedQWord(v: unknown): v is string {
if (typeof v !== 'string') return false;
for (let i = 0; i < v.length; i++) {
if (v[i] === '=' && i + 2 >= v.length) return false;
}
return true;
} Try / catch
try {
mimeDecoding.run(bytes, []);
} catch (e) {
if (e instanceof OperationError && /Incorrectly Encoded Word/.test(e.message)) {
// strip or repair the malformed encoded word, then retry
} else throw e;
} Prevention
- Re-acquire truncated headers from the original message source.
- Validate that every '=' inside a Q-word is followed by two hex digits.
- Strip malformed encoded words rather than letting them abort the whole decode.
When it happens
Trigger: A Q-encoded word ending in a dangling '=', e.g. =?UTF-8?Q?abc= ?=, =?UTF-8?Q?ab=A?=, or =?UTF-8?Q?x=4?= — any case where '=' is not followed by exactly two hex digits before the closing '?='. Raised at MIMEDecoding.mjs:152.
Common situations: Headers truncated by a line-wrap/transport issue; a malformed '=' introduced by mis-escaping; copy/paste that chopped the end of the encoded word; an encoder bug that emitted an incomplete escape.
Related errors
- Unhandled Charset
- Data is not a valid ${Dish.enumLookup(type)}: ${sample}
- ${this.name} cannot be empty.
- ${this.name} length cannot exceed ${this.maxLength}.
- ${this.name} must be a number.
AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13).
Data as JSON: /api/errors/49b566a8b2bce03a.
Report an issue: GitHub.