apache/iceberg · error · IcebergParseException
Invalid transform argument
Error message
Invalid transform argument
What it means
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.
Source
Thrown at spark/v4.0/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSqlExtensionsAstBuilder.scala:315
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)])
}
override def visitSingleStatement(ctx: SingleStatementContext): LogicalPlan = withOrigin(ctx) {
visit(ctx.statement).asInstanceOf[LogicalPlan]
}View on GitHub (pinned to 86d9c8fc54)
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
Example fix
// before ALTER TABLE t PARTITIONED BY (bucket(16)); // after ALTER TABLE t PARTITIONED BY (bucket(16, id));
Defensive patterns
Strategy: validation
Validate before calling
def validateTransformArgs(args: Seq[Any]): Boolean = args.forall {
case _: String => true // column name
case _: Number | _: Boolean => true // literal
case _ => false
} Try / catch
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) } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid transform argument
- Cannot parse order: parser is not an Iceberg ExtendedParser
- Transform is not supported: ${transform}
- Cannot find width for transform: %s
- Cannot parse order: parser is not an Iceberg ExtendedParser
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/801ef0e52558bdda.
Report an issue: GitHub.