prestodb/presto · error · IllegalStateException

e.getMessage()

Error message

e.getMessage()

What it means

parseTransactionId wraps any exception from TransactionId.valueOf into an IllegalStateException carrying only e.getMessage(). It means the X-Presto-Transaction-Id header value is not a valid encoded transaction id, so the router cannot reconstruct the transaction for session routing.

Source

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

                throw new IllegalStateException(format("Invalid %s header: %s", PRESTO_PREPARED_STATEMENT, e.getMessage()));
            }

            preparedStatements.put(statementName, sqlString);
        }
        return preparedStatements.build();
    }

    private static Optional<TransactionId> parseTransactionId(String transactionId)
    {
        transactionId = trimEmptyToNull(transactionId);
        if (transactionId == null || transactionId.equalsIgnoreCase("none")) {
            return Optional.empty();
        }
        try {
            return Optional.of(TransactionId.valueOf(transactionId));
        }
        catch (Exception e) {
            throw new IllegalStateException(e.getMessage());
        }
    }

    private static Map<SqlFunctionId, SqlInvokedFunction> parseSessionFunctionHeader(Map<String, List<String>> headerMap)
    {
        ImmutableMap.Builder<SqlFunctionId, SqlInvokedFunction> sessionFunctions = ImmutableMap.builder();
        for (String header : splitSessionHeader(headerMap.getOrDefault(PRESTO_SESSION_FUNCTION, emptyList()))) {
            List<String> nameValue = Splitter.on('=').limit(2).trimResults().splitToList(header);
            assertRequest(nameValue.size() == 2, "Invalid %s header", PRESTO_SESSION_FUNCTION);

            String serializedFunctionSignature;
            String serializedFunctionDefinition;
            try {
                serializedFunctionSignature = urlDecode(nameValue.get(0));
                serializedFunctionDefinition = urlDecode(nameValue.get(1));
            }
            catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(format("Invalid %s header: %s", PRESTO_SESSION_FUNCTION, e.getMessage()));

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Remove the X-Presto-Transaction-Id header so the router starts a fresh (autocommit) session
  2. Reuse the transaction id exactly as issued by the coordinator's response headers, unmodified
  3. Verify the id was not truncated/mangled by an intermediary; resend the request unmodified from the original client

Example fix

// before
curl -H "X-Presto-Transaction-Id: 'some id'" ...
// after
curl -H "X-Presto-Transaction-Id: 5f0a...full-issued-id..." ...
Defensive patterns

Strategy: validation

Validate before calling

boolean looksLikeTransactionId(String v) {
    return v != null && !v.isBlank() && v.trim().equals(v) && !v.contains(" ");
}

Try / catch

try { routerCall(request); }
catch (IllegalStateException e) { log.warn("Dropping bad transaction id: {}", e.getMessage()); request.removeHeader("X-Presto-Transaction-Id"); retryWithoutTransaction(); }

Prevention

When it happens

Trigger: A request carries X-Presto-Transaction-Id with a corrupted, truncated, or hand-crafted value that TransactionId.valueOf cannot decode (bad base64/UUID structure).

Common situations: Copy-pasting a transaction id with whitespace or quotes into a curl test, stale ids from a restarted cluster, proxies mangling long header values.

Related errors


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