prestodb/presto · error · IllegalStateException

Invalid %s header

Error message

Invalid %s header

What it means

parseSessionProperties throws this when an entry of the X-Presto-Session header has neither one nor two '='-separated name parts — i.e. it is not 'property=value' nor 'catalog.property=value'. The router cannot map the entry to a system or catalog session property.

Source

Thrown at presto-plan-checker-router-plugin/src/main/java/com/facebook/presto/router/scheduler/HttpRequestSessionContext.java:456

        // parse session properties
        ImmutableMap.Builder<String, String> systemProperties = ImmutableMap.builder();
        for (Map.Entry<String, String> entry : parseSessionHeaders(headerMap).entrySet()) {
            String fullPropertyName = entry.getKey();
            String propertyValue = entry.getValue();
            List<String> nameParts = DOT_SPLITTER.splitToList(fullPropertyName);
            if (nameParts.size() == 1) {
                String propertyName = nameParts.get(0);

                assertRequest(!propertyName.isEmpty(), "Invalid %s header", PRESTO_SESSION);

                // catalog session properties can not be validated until the transaction has stated, so we delay system property validation also
                systemProperties.put(propertyName, propertyValue);
            }
            else if (nameParts.size() == 2) {
                continue;
            }
            else {
                throw new IllegalStateException(format("Invalid %s header", PRESTO_SESSION));
            }
        }
        return systemProperties.build();
    }

    private static Map<String, Map<String, String>> parseCatalogSessionProperties(Map<String, List<String>> headerMap)
    {
        Map<String, Map<String, String>> catalogSessionProperties = new HashMap<>();
        for (Map.Entry<String, String> entry : parseSessionHeaders(headerMap).entrySet()) {
            String fullPropertyName = entry.getKey();
            String propertyValue = entry.getValue();
            List<String> nameParts = DOT_SPLITTER.splitToList(fullPropertyName);
            if (nameParts.size() == 1) {
                continue;
            }
            if (nameParts.size() == 2) {
                String catalogName = nameParts.get(0);
                String propertyName = nameParts.get(1);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Rewrite the entry as name=value (system property) or catalog.name=value (catalog property)
  2. Check the client configuration that produces the header for stray '=' or ',' characters
  3. Use the official client which formats the header correctly

Example fix

// before
X-Presto-Session: query_max_memory
// after
X-Presto-Session: query_max_memory=10GB
Defensive patterns

Strategy: validation

Validate before calling

for (String entry : sessionHeader.split(",")) {
    long eq = entry.chars().filter(c -> c == '=').count();
    if (eq != 1 && eq != 2) throw new IllegalArgumentException("Invalid X-Presto-Session entry: " + entry);
}

Try / catch

try { new HttpRequestSessionContext(request, opts); }
catch (IllegalStateException e) { if (e.getMessage().contains("Invalid X-Presto-Session header")) return Response.status(400).build(); throw e; }

Prevention

When it happens

Trigger: An X-Presto-Session value like 'foo' (no '='), 'a=b=c' (three parts) or an empty fragment between commas reaches the final else branch and throws.

Common situations: Hand-edited header values, shell/config escaping stripping or duplicating '=', clients from mismatched versions emitting extra separators, trailing commas producing empty entries.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/f049269ba72feee8. Report an issue: GitHub.