{"record":{"id":"7eb9ae856999677a","repo":"eclipse-vertx/vert.x","slug":"partial-escape-sequence-at-end-of-string-s","errorCode":null,"errorMessage":"partial escape sequence at end of string: ${s}","messagePattern":"partial 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":90,"sourceCode":"  }\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);\n        }\n        c = (char) (c * 16 + c2);\n        // shouldn't check for plus since it would be a double decoding\n        buf[pos++] = (byte) c;\n      } else {\n        buf[pos++] = (byte) (plus && c == '+' ? ' ' : c);\n      }\n    }\n    return new String(buf, 0, pos, StandardCharsets.UTF_8);","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/internal/net/RFC3986.java#L72-L108","documentation":"URI decoding failure in decodeAndTransformURIComponent: a percent sign is followed by only one character before the string ends (and it is not a second '%'), leaving an incomplete two-hex-digit escape sequence. The offending string is included in the message.","triggerScenarios":"Thrown at vertx-core/src/main/java/io/vertx/core/internal/net/RFC3986.java:90 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Complete or remove the partial escape sequence","Percent-encode stray '%' characters as '%25' 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"}