{"record":{"id":"91a7fb543050c111","repo":"quarkusio/quarkus","slug":"length-must-be-1-2-or-6-but-was","errorCode":null,"errorMessage":"Length must be 1, 2 or 6 but was: ","messagePattern":"Length must be 1, 2 or 6 but was: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/qute/core/src/main/java/io/quarkus/qute/JsonEscaper.java","lineNumber":33,"sourceCode":"\n    /**\n     * Packs the replacement data into a single int.<br>\n     * The replacement data is packed as follows:<br>\n     * write an ASCII art of the int:<br>\n     * The visual order chosen reflect what Integer::toHexString would print since Java ints are stored big-endian.<br>\n     *\n     * <pre>\n     *         |----------|-----------|-------------|------------|\n     *  bits   |   24-31  |   16-23   |    8-15     |    0-7     |\n     *  field  |  length  |  padding  |   2nd char  |  1st char  |\n     *  values |  {1,2,6} |    [0]    |   [0-255]   |   [0-255]  |\n     *         |----------|-----------|-------------|------------|\n     * </pre>\n     *\n     */\n    private static int packReplacementData(int first, int second, int length) {\n        if (length != 1 && length != 2 && length != 6) {\n            throw new IllegalArgumentException(\"Length must be 1, 2 or 6 but was: \" + length);\n        }\n        if (first < 0 || first > 255) {\n            throw new IllegalArgumentException(\"First char must be in range [0, 255] but was: \" + first);\n        }\n        if (second < 0 || second > 255) {\n            throw new IllegalArgumentException(\"Second char must be in range [0, 255] but was: \" + second);\n        }\n        return (first | (second << SECOND_CHAR_OFFSET)) | (length << LENGTH_BITS_OFFSET);\n    }\n\n    private static int replacementLength(int replacementData) {\n        // length isn't bigger than 127, which means preserving sign (which is faster) won't affect the shift\n        return replacementData >> LENGTH_BITS_OFFSET;\n    }\n\n    private static char secondChar(int replacementData) {\n        // since past the second char we have padding === 0 we can just cast to char\n        return (char) (replacementData >> SECOND_CHAR_OFFSET);","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/qute/core/src/main/java/io/quarkus/qute/JsonEscaper.java#L15-L51","documentation":"JsonEscaper packs escape-replacement metadata (two chars plus a length of 1, 2, or 6) into a single int via bit packing. Length 1 is a simple single-char replacement, 2 a two-char replacement like \\n, and 6 a unicode escape like \\u0001. Any other length would corrupt the packed int, so IllegalArgumentException is thrown. This is an internal invariant of table generation for JSON escaping.","triggerScenarios":"Calling the private packReplacementData with a length other than 1, 2, or 6 — only possible when modifying JsonEscaper's replacement tables (e.g. adding a new escape entry with a wrong replacement length) or via reflection.","commonSituations":"Developers contributing new escaped characters to Qute's JSON escaper and mis-specifying the replacement string length; not reachable from user templates.","solutions":["Use only replacement strings whose escaped length is 1 (e.g. one char), 2 (e.g. \\\\n), or 6 (e.g. \\\\uXXXX)","Recompute the length argument from the replacement string: \"\\\\n\".length()==2, \"\\\\u0041\".length()==6","If you need a different replacement length, extend the bit-packing scheme (LENGTH_BITS_OFFSET) rather than passing an out-of-range value"],"exampleFix":"// before\npackReplacementData('a', 'x', 3); // throws\n// after\npackReplacementData('\\\\', 'n', 2); // encodes the two-char replacement \\n","handlingStrategy":"validation","validationCode":"if (length != 1 && length != 2 && length != 6) {\n    throw new IllegalArgumentException(\"length must be 1, 2 or 6, got \" + length);\n}","typeGuard":"boolean isValidReplacementLength(int len) {\n    return len == 1 || len == 2 || len == 6;\n}","tryCatchPattern":"try {\n    int packed = packReplacementData(first, second, length);\n} catch (IllegalArgumentException e) {\n    log.error(\"Bad replacement metadata: \" + e.getMessage());\n    throw e;\n}","preventionTips":["Derive length from the replacement string's actual length","Only add replacements of 1, 2, or 6 chars","Add unit tests for any new escape table entry"],"tags":["qute","json","escaping","internal","bit-packing"],"backgroundTag":"invalid-argument-range","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}