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

  1. Convert all arguments to named form: param => value for every argument
  2. 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

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


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)