{"record":{"id":"0f51c8b3df877629","repo":"prestodb/presto","slug":"invalid-s-header-s","errorCode":null,"errorMessage":"Invalid %s header: %s","messagePattern":"Invalid (.+?) header: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-plan-checker-router-plugin/src/main/java/com/facebook/presto/router/scheduler/HttpRequestSessionContext.java","lineNumber":384,"sourceCode":"            throw new IllegalStateException(format(format, args));\n        }\n    }\n\n    private static Map<String, String> parsePreparedStatementsHeaders(Map<String, List<String>> headerMap, SqlParserOptions sqlParserOptions)\n    {\n        ImmutableMap.Builder<String, String> preparedStatements = ImmutableMap.builder();\n        for (String header : splitSessionHeader(headerMap.getOrDefault(PRESTO_PREPARED_STATEMENT, emptyList()))) {\n            List<String> nameValue = Splitter.on('=').limit(2).trimResults().splitToList(header);\n            assertRequest(nameValue.size() == 2, \"Invalid %s header\", PRESTO_PREPARED_STATEMENT);\n\n            String statementName;\n            String sqlString;\n            try {\n                statementName = urlDecode(nameValue.get(0));\n                sqlString = urlDecode(nameValue.get(1));\n            }\n            catch (IllegalArgumentException e) {\n                throw new IllegalArgumentException((format(\"Invalid %s header: %s\", PRESTO_PREPARED_STATEMENT, e.getMessage())));\n            }\n\n            // Validate statement\n            SqlParser sqlParser = new SqlParser(sqlParserOptions);\n            try {\n                sqlParser.createStatement(sqlString, new ParsingOptions(AS_DOUBLE /* anything */));\n            }\n            catch (ParsingException e) {\n                throw new IllegalStateException(format(\"Invalid %s header: %s\", PRESTO_PREPARED_STATEMENT, e.getMessage()));\n            }\n\n            preparedStatements.put(statementName, sqlString);\n        }\n        return preparedStatements.build();\n    }\n\n    private static Optional<TransactionId> parseTransactionId(String transactionId)\n    {","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-plan-checker-router-plugin/src/main/java/com/facebook/presto/router/scheduler/HttpRequestSessionContext.java#L366-L402","documentation":"Thrown by parsePreparedStatementsHeaders when an entry of the X-Presto-Prepared-Statement header cannot be URL-decoded (name or SQL text), wrapping the decoder's IllegalArgumentException with the header name and cause. The header entries must be properly percent-encoded name=SQL pairs.","triggerScenarios":"A prepared statement header value contains raw characters like '%', '=', or non-ASCII SQL text that was not percent-encoded, so urlDecode throws IllegalArgumentException for that entry.","commonSituations":"Clients building the header manually without URL-encoding the SQL string, double-encoding or truncation by intermediaries/proxies, pasting a statement containing a literal '%' into a config.","solutions":["URL-encode both the statement name and the SQL text before placing them in the X-Presto-Prepared-Statement header","Use the official client/StatementClient code path which encodes the header automatically instead of hand-building it","Inspect the wrapped IllegalArgumentException message to find the exact undecodable sequence"],"exampleFix":"// before\nheader: SELECT * FROM t WHERE x LIKE 'a%'\n// after\nheader: SELECT%20*%20FROM%20t%20WHERE%20x%20LIKE%20%27a%25%27","handlingStrategy":"validation","validationCode":"String encoded = URLEncoder.encode(sql, StandardCharsets.UTF_8);\n// verify it round-trips\nif (!URLDecoder.decode(encoded, StandardCharsets.UTF_8).equals(sql)) { throw new IllegalStateException(\"Encoding mismatch\"); }","typeGuard":null,"tryCatchPattern":"try { parsePreparedStatementsHeaders(headerMap, opts); }\ncatch (IllegalArgumentException e) { log.warn(\"Prepared statement header rejected: {}\", e.getMessage()); return Response.status(400).build(); }","preventionTips":["Always URL-encode prepared statement names and SQL","Prefer the official Presto client's header construction","Watch for intermediaries rewriting or truncating header values"],"tags":["http-header","url-encoding","prepared-statement"],"backgroundTag":"invalid-url-encoding","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}