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
- Keep exactly one DETERMINISTIC or NOT DETERMINISTIC clause.
- Make the SQL builder overwrite rather than append determinism settings.
- Validate characteristic uniqueness before submitting the statement.
- 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
- Model determinism as a boolean in application code and render it once.
- Deduplicate characteristics when merging config sources.
- Snapshot-test generated CREATE FUNCTION DDL.
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
- Duplicate language clause: %s
- Duplicate null-call clause: %s
- WARNING_AS_ERROR
- GENERIC_USER_ERROR
- Unsupported EXPLAIN format:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/d1483a17d41b6f43.
Report an issue: GitHub.