{"record":{"id":"f396c0086e431301","repo":"apache/iceberg","slug":"duplicate-parameter-names-duplicateparamnames-m","errorCode":null,"errorMessage":"Duplicate parameter names: ${duplicateParamNames.mkString(\"[\", \",\", \"]\")}","messagePattern":"Duplicate parameter names: (.+?)","errorType":"exception","errorClass":"AnalysisException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveProcedures.scala","lineNumber":63,"sourceCode":"    case CallStatement(CatalogAndIdentifier(catalog, ident), args) =>\n      val procedure = catalog.asProcedureCatalog.loadProcedure(ident)\n\n      val params = procedure.parameters\n      val normalizedParams = normalizeParams(params)\n      validateParams(normalizedParams)\n\n      val normalizedArgs = normalizeArgs(args)\n      Call(procedure, args = buildArgExprs(normalizedParams, normalizedArgs).toSeq)\n  }\n\n  private def validateParams(params: Seq[ProcedureParameter]): Unit = {\n    // should not be any duplicate param names\n    val duplicateParamNames = params.groupBy(_.name).collect {\n      case (name, matchingParams) if matchingParams.length > 1 => name\n    }\n\n    if (duplicateParamNames.nonEmpty) {\n      throw new AnalysisException(\n        s\"Duplicate parameter names: ${duplicateParamNames.mkString(\"[\", \",\", \"]\")}\")\n    }\n\n    // optional params should be at the end\n    params.sliding(2).foreach {\n      case Seq(previousParam, currentParam) if !previousParam.required && currentParam.required =>\n        throw new AnalysisException(\n          s\"Optional parameters must be after required ones but $currentParam is after $previousParam\")\n      case _ =>\n    }\n  }\n\n  private def buildArgExprs(\n      params: Seq[ProcedureParameter],\n      args: Seq[CallArgument]): Seq[Expression] = {\n\n    // build a map of declared parameter names to their positions\n    val nameToPositionMap = params.map(_.name).zipWithIndex.toMap","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveProcedures.scala#L45-L81","documentation":"Thrown by ResolveProcedures when a procedure's parameter list contains two or more parameters sharing the same name. Duplicate names make named-argument invocation ambiguous, so procedure resolution rejects it at analysis time.","triggerScenarios":"Registering/defining a procedure whose ProcedureParameter list has repeated names, then resolving a CALL against it.","commonSituations":"Programmatic procedure definitions where parameters are generated from a schema and two columns share a (case-insensitively equal) name; hand-rolled procedure catalogs with copy-pasted parameter declarations.","solutions":["Rename one of the duplicated procedure parameters so every parameter name is unique","If parameters are generated from schema fields, deduplicate or prefix field names before building ProcedureParameter instances"],"exampleFix":"// before\nProcedureParameter.required(\"table\"), ProcedureParameter.optional(\"table\", StringType)\n// after\nProcedureParameter.required(\"table\"), ProcedureParameter.optional(\"where\", StringType)","handlingStrategy":"validation","validationCode":"val names = params.map(_.name)\nrequire(names.distinct.size == names.size, s\"duplicate param names: ${names.diff(names.distinct).mkString(\",\")}\")","typeGuard":null,"tryCatchPattern":"try { spark.sql(callSql) } catch { case e: AnalysisException if e.getMessage.startsWith(\"Duplicate parameter names\") => // fix procedure definition }","preventionTips":["Generate procedure parameters from deduplicated schema field names","Add a unit test asserting parameter name uniqueness for custom procedures"],"tags":["spark","sql","procedures","analysis"],"backgroundTag":"invalid-argument-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}