apache/iceberg · error
Named and positional arguments cannot be mixed
Error message
Named and positional arguments cannot be mixed
What it means
Thrown by ResolveProcedures when a single CALL mixes positional and named arguments. Iceberg requires invocation to use entirely positional or entirely named arguments; mixing makes the mapping ambiguous, so analysis fails.
Solutions
- Convert all arguments to named form: param => value for every argument
- Convert all arguments to positional form, ordering them exactly as the procedure declares them
Example fix
// before
CALL catalog.system.rewrite_data_files('db.t', where => 'id > 1')
// after
CALL catalog.system.rewrite_data_files(table => 'db.t', where => 'id > 1') Defensive patterns
Strategy: validation
Validate before calling
val styles = callArgs.map(a => if (a.isInstanceOf[NamedArgument]) "named" else "positional").distinct require(styles.size <= 1, "CALL must use all named or all positional arguments")
Try / catch
try { spark.sql(callSql) } catch { case e: AnalysisException if e.getMessage == "Named and positional arguments cannot be mixed" => // normalize argument style } Prevention
- Standardize on fully named invocation for procedures with optional parameters
- Never append a named argument to an existing positional call — convert all arguments at once
When it happens
Trigger: CALL catalog.system.proc('db.t', where => 'id > 1') — first arg positional, second named.
Common situations: Extending an existing positional call with a named argument for one optional parameter; copying example DDL that used the other invocation style.
Related errors
- Could not build name to arg map
- Missing required parameters
- Cannot use catalog : not a ProcedureCatalog
- Too many arguments for procedure
- Wrong arg type for : cannot cast $argType to $paramType
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/bb7dc46f5d97bd43.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveProcedures.scala:123
case p if !p.required && !nameToArgMap.contains(p.name) =>
val position = nameToPositionMap(p.name)
argExprs(position) = Literal.create(null, p.dataType)
case _ =>
}
argExprs
}
private def buildNameToArgMap(
params: Seq[ProcedureParameter],
args: Seq[CallArgument],
nameToPositionMap: Map[String, Int]): Map[String, CallArgument] = {
val containsNamedArg = args.exists(_.isInstanceOf[NamedArgument])
val containsPositionalArg = args.exists(_.isInstanceOf[PositionalArgument])
if (containsNamedArg && containsPositionalArg) {
throw new AnalysisException("Named and positional arguments cannot be mixed")
}
if (containsNamedArg) {
buildNameToArgMapUsingNames(args, nameToPositionMap)
} else {
buildNameToArgMapUsingPositions(args, params)
}
}
private def buildNameToArgMapUsingNames(
args: Seq[CallArgument],
nameToPositionMap: Map[String, Int]): Map[String, CallArgument] = {
val namedArgs = args.asInstanceOf[Seq[NamedArgument]]
val validationErrors = namedArgs.groupBy(_.name).collect {
case (name, matchingArgs) if matchingArgs.size > 1 => s"Duplicate procedure argument: $name"
case (name, _) if !nameToPositionMap.contains(name) => s"Unknown argument: $name"View on GitHub (pinned to 86d9c8fc54)