prestodb/presto · error · PrestoException
INVALID_ARGUMENTS
INVALID_ARGUMENTS
Error message
Missing variable:
What it means
PushdownSubfields rewrites table scans to push down only the subfields (nested column paths) actually referenced by the query. For every scan output variable it looks up tracked subfields; if a variable has no recorded subfields it throws INVALID_ARGUMENTS 'Missing variable: <name>'. This indicates the subfield tracking pass missed a variable the scan exposes.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PushdownSubfields.java:389
public PlanNode visitTableScan(TableScanNode node, RewriteContext<Context> context)
{
if (context.get().subfields.isEmpty()) {
return node;
}
ImmutableMap.Builder<VariableReferenceExpression, ColumnHandle> newAssignments = ImmutableMap.builder();
for (Map.Entry<VariableReferenceExpression, ColumnHandle> entry : node.getAssignments().entrySet()) {
VariableReferenceExpression variable = entry.getKey();
if (context.get().variables.contains(variable)) {
newAssignments.put(entry);
continue;
}
List<Subfield> subfields = context.get().findSubfields(variable.getName());
if (subfields.isEmpty()) {
throw new PrestoException(INVALID_ARGUMENTS, "Missing variable: " + variable);
}
String columnName = getColumnName(session, metadata, node.getTable(), entry.getValue());
List<Subfield> subfieldsWithoutNoSubfield = subfields.stream().filter(subfield -> !containsNoSubfieldPathElement(subfield)).collect(toList());
List<Subfield> subfieldsWithNoSubfield = subfields.stream().filter(subfield -> containsNoSubfieldPathElement(subfield)).collect(toList());
// Prune subfields: if one subfield is a prefix of another subfield, keep the shortest one.
// Example: {a.b.c, a.b} -> {a.b}
List<Subfield> columnSubfields = subfieldsWithoutNoSubfield.stream()
.filter(subfield -> !prefixExists(subfield, subfieldsWithoutNoSubfield))
.map(Subfield::getPath)
.map(path -> new Subfield(columnName, path))
.collect(toList());
columnSubfields.addAll(subfieldsWithNoSubfield.stream()
.filter(subfield -> !isPrefixOf(dropNoSubfield(subfield), subfieldsWithoutNoSubfield))
.map(Subfield::getPath)View on GitHub (pinned to 55bb57d202)
Solutions
- Reduce the query to identify which expression over the nested column loses subfield tracking, and rewrite it (e.g. extract the needed subfield earlier into a subquery).
- File a bug with the query and EXPLAIN so PushdownSubfields can be extended for the missed pattern.
- Disable the subfield pushdown optimization for the session to unblock the query.
Example fix
// before SELECT CAST(nested_col AS ROW(a INTEGER)).a FROM t; // after SELECT nested_col.a FROM t; -- keeps subfield tracking on the variable
Defensive patterns
Strategy: fallback
Try / catch
try {
plan = planQuery(sql);
} catch (PrestoException e) {
if ("INVALID_ARGUMENTS".equals(e.getErrorCode().getName()) && e.getMessage().startsWith("Missing variable:")) {
plan = planQuery(sql, /* disableSubfieldPushdown */ true);
} else throw e;
} Prevention
- Prefer direct nested-field references (row_col.a) over casts of whole nested columns
- Keep nested-type expressions simple; precompute complex expressions in inner queries
- Report queries that trigger it so PushdownSubfields coverage improves
When it happens
Trigger: A table scan output variable is not present in the subfield context built by this optimizer — typically a nested-row/column variable referenced by the query for which findSubfields returns empty during visitTableScan.
Common situations: Queries over nested row types / complex columns where the subfield extraction rules do not cover an expression referencing the variable; planner rule interaction bugs; casting or function usage that strips subfield association.
Related errors
- BIGQUERY_UNSUPPORTED_TYPE_FOR_BLOCK
- INVALID_ARGUMENTS
- GENERIC_INTERNAL_ERROR
- NOT_SUPPORTED
- INVALID_ARGUMENTS
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/9c9486e8b2ddcca3.
Report an issue: GitHub.