apache/iceberg · error · IcebergParseException

e.message (wrapped as IcebergParseException with command con

Error message

e.message (wrapped as IcebergParseException with command context)

What it means

When the Iceberg SQL extension parser hits an AnalysisException during parsing that is not already an IcebergParseException, it wraps the failure in an IcebergParseException carrying the offending SQL command text for better diagnostics. The message shown to the user is the underlying AnalysisException's message, so the real problem is described by the wrapped cause, not by Iceberg itself.

Source

Thrown at spark/v4.2/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSparkSqlExtensionsParser.scala:224

      } catch {
        case _: ParseCancellationException =>
          // if we fail, parse with LL mode with DefaultErrorStrategy
          tokenStream.seek(0) // rewind input stream
          parser.reset()

          // Try Again.
          parser.setErrorHandler(new DefaultErrorStrategy)
          parser.getInterpreter.setPredictionMode(PredictionMode.LL)
          toResult(parser)
      }
    } catch {
      case e: IcebergParseException if e.command.isDefined =>
        throw e
      case e: IcebergParseException =>
        throw e.withCommand(command)
      case e: AnalysisException =>
        val position = Origin(e.line, e.startPosition)
        throw new IcebergParseException(Option(command), e.message, position, position)
    }
  }

  override def parseQuery(sqlText: String): LogicalPlan = {
    parsePlan(sqlText)
  }
}

object IcebergSparkSqlExtensionsParser {
  private val substitutorCtor: DynConstructors.Ctor[VariableSubstitution] =
    DynConstructors
      .builder()
      .impl(classOf[VariableSubstitution])
      .impl(classOf[VariableSubstitution], classOf[SQLConf])
      .build()
}

/* Copied from Apache Spark's to avoid dependency on Spark Internals */

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Read the wrapped message (the actual AnalysisException text) and fix the underlying SQL problem it describes.
  2. Print/check the command attached to the IcebergParseException to confirm which SQL text failed.
  3. Compare your statement against the Iceberg extension grammar documentation for the exact accepted syntax.
  4. If the SQL is valid but fails due to a parser-side bug, upgrade the iceberg-spark-extensions artifact to match your Spark version.

Example fix

// catch the wrapper and inspect cause
catch {
  case e: IcebergParseException =>
    log.error(s"Failed command: ${e.command.getOrElse("<unknown>")}", e)
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  spark.sql(extensionStatement)
} catch {
  case e: IcebergParseException =>
    e.command.foreach(c => log.error(s"Failing SQL: $c"))
    throw new IllegalArgumentException(s"Bad Iceberg SQL: ${e.getMessage}", e)
}

Prevention

When it happens

Trigger: Parsing an Iceberg-extension SQL statement (e.g. CALL, ALTER TABLE ... WRITE ORDERED BY, MERGE branches) whose parse-time resolution fails with a plain Spark AnalysisException; the parser catches it and rethrows with command context attached.

Common situations: Syntax accepted by the grammar but referencing something that fails during parsing callbacks (bad multipart identifiers, invalid literals); mixing Spark SQL that only partially matches the Iceberg grammar.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/fc95226554724b2a. Report an issue: GitHub.