{"record":{"id":"85ac77a4fa9df9fd","repo":"eclipse-vertx/vert.x","slug":"unterminated-escape-sequence-at-end-of-string-s","errorCode":null,"errorMessage":"unterminated escape sequence at end of string: ${s}","messagePattern":"unterminated escape sequence at end of string: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/internal/net/RFC3986.java","lineNumber":81,"sourceCode":"\n  private static int indexOfPercentOrPlus(String s) {\n    for (int i = 0, size = s.length(); i < size; i++) {\n      final char c = s.charAt(i);\n      if (c == '%' || c == '+') {\n        return i;\n      }\n    }\n    return -1;\n  }\n\n  private static String decodeAndTransformURIComponent(String s, int i, boolean plus) {\n    final byte[] buf = s.getBytes(StandardCharsets.UTF_8);\n    int pos = i;  // position in `buf'.\n    for (int size = s.length(); i < size; i++) {\n      char c = s.charAt(i);\n      if (c == '%') {\n        if (i == size - 1) {\n          throw new IllegalArgumentException(\"unterminated escape\"\n            + \" sequence at end of string: \" + s);\n        }\n        c = s.charAt(++i);\n        if (c == '%') {\n          buf[pos++] = '%';  // \"%%\" -> \"%\"\n          break;\n        }\n        if (i >= size - 1) {\n          throw new IllegalArgumentException(\"partial escape\"\n            + \" sequence at end of string: \" + s);\n        }\n        c = decodeHexNibble(c);\n        final char c2 = decodeHexNibble(s.charAt(++i));\n        if (c == Character.MAX_VALUE || c2 == Character.MAX_VALUE) {\n          throw new IllegalArgumentException(\n            \"invalid escape sequence `%\" + s.charAt(i - 1)\n              + s.charAt(i) + \"' at index \" + (i - 2)\n              + \" of: \" + s);","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/internal/net/RFC3986.java#L63-L99","documentation":"URI decoding failure in decodeAndTransformURIComponent: a percent sign appears as the last character of the string, so the escape sequence has no following hex digits to decode. The full offending string is included; the input at fault is the URI component being decoded.","triggerScenarios":"Thrown at vertx-core/src/main/java/io/vertx/core/internal/net/RFC3986.java:81 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Fix the truncated percent-encoding or encode lone '%' as '%25'","Validate/normalize URIs from untrusted sources before decoding"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}