{"record":{"id":"801ef0e52558bdda","repo":"apache/iceberg","slug":"invalid-transform-argument-801ef0","errorCode":null,"errorMessage":"Invalid transform argument","messagePattern":"Invalid transform argument","errorType":"exception","errorClass":"IcebergParseException","httpStatus":null,"severity":"error","filePath":"spark/v4.0/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSqlExtensionsAstBuilder.scala","lineNumber":315,"sourceCode":"  override def visitApplyTransform(ctx: ApplyTransformContext): Transform = withOrigin(ctx) {\n    val args = toSeq(ctx.arguments).map(typedVisit[expressions.Expression])\n    ApplyTransform(ctx.transformName.getText, args)\n  }\n\n  /**\n   * Create a transform argument from a column reference or a constant.\n   */\n  override def visitTransformArgument(ctx: TransformArgumentContext): expressions.Expression =\n    withOrigin(ctx) {\n      val reference = Option(ctx.multipartIdentifier())\n        .map(typedVisit[Seq[String]])\n        .map(FieldReference(_))\n      val literal = Option(ctx.constant)\n        .map(visitConstant)\n        .map(lit => LiteralValue(lit.value, lit.dataType))\n      reference\n        .orElse(literal)\n        .getOrElse(throw new IcebergParseException(s\"Invalid transform argument\", ctx))\n    }\n\n  /**\n   * Return a multi-part identifier as Seq[String].\n   */\n  override def visitMultipartIdentifier(ctx: MultipartIdentifierContext): Seq[String] =\n    withOrigin(ctx) {\n      toSeq(ctx.parts).map(_.getText)\n    }\n\n  override def visitSingleOrder(ctx: SingleOrderContext): Seq[(Term, SortDirection, NullOrder)] =\n    withOrigin(ctx) {\n      toSeq(ctx.order.fields).map(typedVisit[(Term, SortDirection, NullOrder)])\n    }\n\n  override def visitSingleStatement(ctx: SingleStatementContext): LogicalPlan = withOrigin(ctx) {\n    visit(ctx.statement).asInstanceOf[LogicalPlan]\n  }","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSqlExtensionsAstBuilder.scala#L297-L333","documentation":"When visiting a transform/procedure argument (e.g. in TRUNCATE-style transforms or CALL argument positions), the builder requires either a column reference or a constant literal. If the context provides neither (empty or unsupported argument), it throws IcebergParseException with 'Invalid transform argument'. The parser cannot bind the argument to a partition-transform operand.","triggerScenarios":"Iceberg extension SQL where a transform argument position holds something that is neither an identifier nor a constant, e.g. `ALTER TABLE ... PARTITIONED BY (years())` with an empty argument, or an expression the grammar does not accept in that slot.","commonSituations":"Writing `bucket()` or `truncate()` with missing arguments in DDL, passing complex expressions where only a column or literal is allowed, or copy-pasting syntax from other engines.","solutions":["Pass a column: e.g. bucket(16, id)","Pass a constant literal where allowed: e.g. truncate(10, 'literal')","Remove the malformed argument or use supported transform syntax per Iceberg docs"],"exampleFix":"// before\nALTER TABLE t PARTITIONED BY (bucket(16));\n// after\nALTER TABLE t PARTITIONED BY (bucket(16, id));","handlingStrategy":"validation","validationCode":"def validateTransformArgs(args: Seq[Any]): Boolean = args.forall {\n  case _: String => true // column name\n  case _: Number | _: Boolean => true // literal\n  case _ => false\n}","typeGuard":null,"tryCatchPattern":"try { spark.sql(ddl) } catch { case e: IcebergParseException if e.getMessage.contains(\"Invalid transform argument\") => log.error(\"Transform args must be a column or literal\", e) }","preventionTips":["Always supply required transform parameters, e.g. bucket(n, col), truncate(w, col)","Use only identifiers or literals in transform argument positions","Cross-check transform syntax against Iceberg partitioning docs"],"tags":["spark","parser","transform","argument"],"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-14T16:17:12.679Z"}