prestodb/presto · error · ParsingException
Duplicate null-call clause: %s
Error message
Duplicate null-call clause: %s
What it means
Duplicate-clause guard in the routine-characteristics loop of AstBuilder: a CREATE FUNCTION statement specifies the NULL ON INPUT / RETURNS NULL ON NULL INPUT / CALLED ON NULL INPUT clause more than once. The second null-call clause triggers a ParsingException at its location.
Source
Thrown at presto-parser/src/main/java/com/facebook/presto/sql/parser/AstBuilder.java:3081
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));
}
private AlterRoutineCharacteristics getAlterRoutineCharacteristics(SqlBaseParser.AlterRoutineCharacteristicsContext context)
{
if (context.alterRoutineCharacteristic().isEmpty()) {
throw new ParsingException("No alter routine characteristics specified");View on GitHub (pinned to 55bb57d202)
Solutions
- Emit only one CALLED ON NULL INPUT or RETURNS NULL ON NULL INPUT clause.
- Deduplicate characteristics when composing function DDL.
- Pre-validate the characteristic list before parsing.
- Fix DDL generation to replace, not append, the null-call setting.
Example fix
// before CREATE FUNCTION f() RETURNS int CALLED ON NULL INPUT RETURNS NULL ON NULL INPUT RETURN 1; // after CREATE FUNCTION f() RETURNS int RETURNS NULL ON NULL INPUT RETURN 1;
Defensive patterns
Strategy: validation
Validate before calling
int nullCallClauses = countMatches(sql, "(?i)\\b(CALLED\\s+ON\\s+NULL\\s+INPUT|RETURNS\\s+NULL\\s+ON\\s+NULL\\s+INPUT)\\b");
if (nullCallClauses > 1) {
throw new IllegalArgumentException("Only one null-call clause allowed");
} Type guard
boolean hasSingleNullCallClause(String sql) {
Matcher m = Pattern.compile("(?i)(CALLED ON NULL INPUT|RETURNS NULL ON NULL INPUT)").matcher(sql);
return count(m) <= 1;
} Try / catch
try {
parser.createStatement(sql);
} catch (ParsingException e) {
if (e.getMessage().startsWith("Duplicate null-call clause")) {
throw new IllegalArgumentException("Keep only one CALLED/RETURNS NULL ON NULL INPUT clause", e);
}
throw e;
} Prevention
- Emit the null-call clause from a single nullable field, defaulting to null (omit).
- Deduplicate characteristic fragments when composing DDL.
- Cover function DDL generation with parser round-trip tests.
When it happens
Trigger: Parsing a CREATE FUNCTION whose routine_characteristic list contains two null-call clauses (e.g. 'RETURNS NULL ON NULL INPUT CALLED ON NULL INPUT' or the same clause twice).
Common situations: Generated function DDL that emits a default null-call clause plus a user-specified one, or concatenated SQL fragments each carrying the clause.
Related errors
- Duplicate language clause: %s
- Duplicate determinism characteristics: %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/133914f5caeec077.
Report an issue: GitHub.