prestodb/presto · error · SQLException

No value specified for parameter

Error message

No value specified for parameter 

What it means

Before executing, toValues() walks parameters 0..size-1 and requires every slot to be filled; a gap means at least one placeholder was never bound. Note the count-based check: if a higher index was set while an earlier one was skipped, the earlier one is reported. This prevents sending an incomplete parameter list to the Presto server.

Source

Thrown at presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoPreparedStatement.java:810

        throw new SQLException("This method cannot be called on PreparedStatement");
    }

    private void setParameter(int parameterIndex, String value)
            throws SQLException
    {
        if (parameterIndex < 1) {
            throw new SQLException("Parameter index out of bounds: " + parameterIndex);
        }
        parameters.put(parameterIndex - 1, value);
    }

    private static List<String> toValues(Map<Integer, String> parameters)
            throws SQLException
    {
        ImmutableList.Builder<String> values = ImmutableList.builder();
        for (int index = 0; index < parameters.size(); index++) {
            if (!parameters.containsKey(index)) {
                throw new SQLException("No value specified for parameter " + (index + 1));
            }
            values.add(parameters.get(index));
        }
        return values.build();
    }

    private void requireNonBatchStatement()
            throws SQLException
    {
        if (isBatch) {
            throw new SQLException("Batch prepared statement must be executed using executeBatch method");
        }
    }

    private static String getExecuteSql(String statementName, List<String> values)
    {
        StringBuilder sql = new StringBuilder();
        sql.append("EXECUTE ").append(statementName);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Count the ? placeholders in the SQL and call one setXxx for each index 1..N before executing
  2. Check the message's parameter number to find the first missing binding and add the missing setXxx call
  3. In dynamic/conditional code, ensure every branch binds the same full set of parameters, using setNull for absent values
  4. Bind parameters in ascending index order to keep gaps from hiding behind later bindings

Example fix

// before
ps.setInt(1, id); // placeholder 2 never set
ResultSet rs = ps.executeQuery();
// after
ps.setInt(1, id);
ps.setString(2, name);
ResultSet rs = ps.executeQuery();
Defensive patterns

Strategy: validation

Validate before calling

int placeholders = sql.length() - sql.replace("?", "").length();
if (placeholders != boundParameterCount) {
    throw new IllegalStateException("Expected " + placeholders + " bound parameters, got " + boundParameterCount);
}

Try / catch

catch (SQLException e) {
    if (e.getMessage().startsWith("No value specified for parameter")) {
        int missing = Integer.parseInt(e.getMessage().substring(e.getMessage().lastIndexOf(' ') + 1));
        // bind parameter 'missing' before executing
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing (executeQuery/executeUpdate/executeLargeUpdate/execute/addBatch) a PreparedStatement where some setXxx call was skipped, or where parameters were set out of order leaving an earlier index unset while a later one was set.

Common situations: Conditional binding code that forgets a branch; N placeholders in SQL but only N-1 setters called; setting only parameter 3 in a 3-parameter statement (indexes 0 and 1 never filled); refactoring that removed a parameter from code but not the SQL.

Related errors


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