prestodb/presto · error · ParsingException

Duplicate determinism characteristics: %s

Error message

Duplicate determinism characteristics: %s

What it means

Duplicate-clause guard in the routine-characteristics loop of AstBuilder: a CREATE FUNCTION statement specifies the DETERMINISTIC/NOT DETERMINISTIC characteristic more than once. The second determinism clause is rejected as a ParsingException at its source location, mirroring the duplicate language-clause check.

Source

Thrown at presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java:3075

        Language language = null;
        Determinism determinism = null;
        NullCallClause nullCallClause = null;

        for (SqlBaseParser.RoutineCharacteristicContext characteristic : context.routineCharacteristic()) {
            if (characteristic.language() != null) {
                if (language != null) {
                    throw new ParsingException(format("Duplicate language clause: %s", characteristic.language().getText()), getLocation(characteristic.language()));
                }
                if (characteristic.language().SQL() != null) {
                    language = Language.SQL;
                }
                else {
                    language = new Language(((Identifier) visit(characteristic.language().identifier())).getValue());
                }
            }
            else if (characteristic.determinism() != null) {
                if (determinism != null) {
                    throw new ParsingException(format("Duplicate determinism characteristics: %s", characteristic.determinism().getText()), getLocation(characteristic.determinism()));
                }
                determinism = characteristic.determinism().NOT() == null ? DETERMINISTIC : NOT_DETERMINISTIC;
            }
            else if (characteristic.nullCallClause() != null) {
                if (nullCallClause != null) {
                    throw new ParsingException(format("Duplicate null-call clause: %s", characteristic.nullCallClause().getText()), getLocation(characteristic.nullCallClause()));
                }
                nullCallClause = characteristic.nullCallClause().CALLED() != null ? CALLED_ON_NULL_INPUT : RETURNS_NULL_ON_NULL_INPUT;
            }
            else {
                throw new IllegalArgumentException(format("Unsupported RoutineCharacteristic: %s", characteristic.getText()));
            }
        }

        return new RoutineCharacteristics(
                Optional.ofNullable(language),
                Optional.ofNullable(determinism),
                Optional.ofNullable(nullCallClause));

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Keep exactly one DETERMINISTIC or NOT DETERMINISTIC clause.
  2. Make the SQL builder overwrite rather than append determinism settings.
  3. Validate characteristic uniqueness before submitting the statement.
  4. Fix config merge logic that emits the clause from more than one source.

Example fix

// before
CREATE FUNCTION f() RETURNS int DETERMINISTIC NOT DETERMINISTIC RETURN 1;
// after
CREATE FUNCTION f() RETURNS int DETERMINISTIC RETURN 1;
Defensive patterns

Strategy: validation

Validate before calling

int determinismClauses = countMatches(sql, "(?i)\\b(NOT\\s+)?DETERMINISTIC\\b");
if (determinismClauses > 1) {
    throw new IllegalArgumentException("Only one DETERMINISTIC/NOT DETERMINISTIC allowed");
}

Type guard

boolean hasSingleDeterminismClause(String sql) {
    Matcher m = Pattern.compile("(?i)\\b(NOT\\s+)?DETERMINISTIC\\b").matcher(sql);
    return count(m) <= 1;
}

Try / catch

try {
    parser.createStatement(sql);
} catch (ParsingException e) {
    if (e.getMessage().startsWith("Duplicate determinism characteristics")) {
        throw new IllegalArgumentException("Specify DETERMINISTIC or NOT DETERMINISTIC exactly once", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Parsing 'CREATE FUNCTION ... DETERMINISTIC NOT DETERMINISTIC ...' or repeating the same determinism keyword twice in the characteristics list.

Common situations: SQL generators concatenating characteristic strings from multiple config sources, or users writing both DETERMINISTIC and NOT DETERMINISTIC when toggling behavior.

Related errors


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