prestodb/presto · error · SemanticException
TABLE_FUNCTION_DUPLICATE_RANGE_VARIABLE
TABLE_FUNCTION_DUPLICATE_RANGE_VARIABLE
Error message
Relation alias: %s is a duplicate of input table name: %s
What it means
For a table function invocation with a relation alias, Presto checks that the alias does not duplicate any of the function's input table (range variable) names. The alias would shadow the range variables exposed by the table arguments, making those parameter columns unreferenceable, so the analyzer rejects it with TABLE_FUNCTION_DUPLICATE_RANGE_VARIABLE.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:3103
return createAndAssignScope(relation, scope, descriptor);
}
// As described by the SQL standard ISO/IEC 9075-2, 7.6 <table reference>, p. 409
private RelationType aliasTableFunctionInvocation(AliasedRelation relation, RelationType relationType, TableFunctionInvocation function)
{
TableFunctionInvocationAnalysis tableFunctionAnalysis = analysis.getTableFunctionAnalysis(function);
int properColumnsCount = tableFunctionAnalysis.getProperColumnsCount();
// check that relation alias is different from range variables of all table arguments
tableFunctionAnalysis.getTableArgumentAnalyses().stream()
.map(TableArgumentAnalysis::getName)
.filter(Optional::isPresent)
.map(Optional::get)
.filter(name -> name.hasSuffix(QualifiedName.of(ImmutableList.of(relation.getAlias()))))
.findFirst()
.ifPresent(name -> {
throw new SemanticException(TABLE_FUNCTION_DUPLICATE_RANGE_VARIABLE, relation.getAlias(), "Relation alias: %s is a duplicate of input table name: %s", relation.getAlias(), name);
});
// build the new relation type. the alias must be applied to the proper columns only,
// and it must not shadow the range variables exposed by the table arguments
ImmutableList.Builder<Field> fieldsBuilder = ImmutableList.builder();
// first, put the table function's proper columns with alias
if (relation.getColumnNames() != null) {
// check that number of column aliases matches number of table function's proper columns
if (properColumnsCount != relation.getColumnNames().size()) {
throw new SemanticException(MISMATCHED_COLUMN_ALIASES, relation, "Column alias list has %s entries but table function has %s proper columns", relation.getColumnNames().size(), properColumnsCount);
}
for (int i = 0; i < properColumnsCount; i++) {
// proper columns are not hidden, so we don't need to skip hidden fields
Field field = relationType.getFieldByIndex(i);
fieldsBuilder.add(Field.newQualified(
field.getNodeLocation(),
QualifiedName.of(ImmutableList.of(relation.getAlias())),
Optional.of(relation.getColumnNames().get(i).getCanonicalValue()), // although the canonical name is recorded, fields are resolved case-insensitiveView on GitHub (pinned to 55bb57d202)
Solutions
- Rename the relation alias to something distinct from every input table argument name
- Keep the input table's range variable name and give the invocation a fresh alias
- Drop the explicit alias if original column names are acceptable
Example fix
-- before SELECT * FROM TABLE(f(TABLE(orders) AS orders)) AS orders -- after SELECT * FROM TABLE(f(TABLE(orders) AS orders)) AS f_result
Defensive patterns
Strategy: validation
Validate before calling
Set<String> inputNames = tableFunctionInvocation.getInputTableNames();
if (inputNames.contains(alias)) {
throw new IllegalArgumentException("alias " + alias + " collides with input table name");
} Try / catch
try {
return client.execute(sql);
} catch (SemanticException e) {
if (e.getCode() == SemanticErrorCode.TABLE_FUNCTION_DUPLICATE_RANGE_VARIABLE) {
sql = renameRelationAlias(sql); // pick a non-colliding alias and retry
} else { throw e; }
} Prevention
- Use distinct prefixes for relation aliases (e.g. f_) vs input table range variables
- Document the input table names of each table function used
- Add alias-collision checks in SQL templating code
- Avoid naming the invocation alias after the underlying tables
When it happens
Trigger: Calling a polymorphic table function like TABLE(my_func(TABLE(t) AS t)) where the outer relation alias is the same name as an input table argument, e.g. FROM TABLE(f(TABLE(x) AS x)) AS x.
Common situations: Copy-paste of function examples where the alias coincides with the input table name; auto-generated SQL assigning the function name/table name as alias; refactoring that renames an input table without renaming the alias.
Related errors
- INVALID_FUNCTION_ARGUMENT
- INVALID_TABLE_PROPERTY
- Invalid time from server:
- Expected column to be a time type but is
- Invalid timestamp from server:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/9772a760b0469203.
Report an issue: GitHub.