apache/iceberg · error · IcebergParseException
Invalid transform argument
Error message
Invalid transform argument
What it means
In transforms like bucket(N, arg) or truncate(W, arg), the transform argument must be either a column reference or a constant literal. If the argument context provides neither (missing/unsupported argument form), an IcebergParseException is thrown.
Source
Thrown at spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSqlExtensionsAstBuilder.scala:328
override def visitApplyTransform(ctx: ApplyTransformContext): Transform = withOrigin(ctx) {
val args = toSeq(ctx.arguments).map(typedVisit[expressions.Expression])
ApplyTransform(ctx.transformName.getText, args)
}
/**
* Create a transform argument from a column reference or a constant.
*/
override def visitTransformArgument(ctx: TransformArgumentContext): expressions.Expression =
withOrigin(ctx) {
val reference = Option(ctx.multipartIdentifier())
.map(typedVisit[Seq[String]])
.map(FieldReference(_))
val literal = Option(ctx.constant)
.map(visitConstant)
.map(lit => LiteralValue(lit.value, lit.dataType))
reference
.orElse(literal)
.getOrElse(throw new IcebergParseException(s"Invalid transform argument", ctx))
}
/**
* Return a multi-part identifier as Seq[String].
*/
override def visitMultipartIdentifier(ctx: MultipartIdentifierContext): Seq[String] =
withOrigin(ctx) {
toSeq(ctx.parts).map(_.getText)
}
override def visitSingleOrder(ctx: SingleOrderContext): Seq[(Term, SortDirection, NullOrder)] =
withOrigin(ctx) {
toSeq(ctx.order.fields).map(typedVisit[(Term, SortDirection, NullOrder)])
}
/**
* Create a positional argument in a stored procedure call.
*/View on GitHub (pinned to 86d9c8fc54)
Solutions
- Supply a column name: e.g. PARTITIONED BY (bucket(16, id))
- Supply a constant literal where allowed, e.g. truncate(10, 'abc')
- Verify the transform's grammar — transforms require exactly one argument between the parentheses
Example fix
// before ALTER TABLE t ADD PARTITION FIELD bucket(16, ); // after ALTER TABLE t ADD PARTITION FIELD bucket(16, id);
Defensive patterns
Strategy: validation
Validate before calling
val transform = "bucket\\(([^)]*)\\)".r.findAllIn(ddl).toList
transform.foreach(t => require(t.split(",").length == 2 && t.trim.endsWith(")") && !t.endsWith("(, )"), s"Transform needs a column or literal argument: $t") Try / catch
try { spark.sql(ddl) } catch { case e: IcebergParseException if e.getMessage.contains("Invalid transform argument") => log.error("empty transform argument"); throw e } Prevention
- Always pass a column reference or literal as the second transform argument
- Never template transforms with empty placeholders
- Check Iceberg transform grammar (bucket/truncate/year/month/day/hour) before writing DDL
When it happens
Trigger: Parsing a partition transform with an empty or non-reference/non-constant argument, e.g. 'bucket(2, )' or grammar contexts where ctx.field and ctx.constant are both absent.
Common situations: Hand-written DDL with a missing transform argument; macro/template-generated SQL leaving a placeholder empty.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Cannot write using unsupported transforms: %s
- Invalid transform argument
- Cannot bind unsupported transform: %s
- Unsupported transform: ${transform}
- Cannot parse order: parser is not an Iceberg ExtendedParser
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/741ba9db05a2517d.
Report an issue: GitHub.