{"record":{"id":"011bb2f6c5942233","repo":"apache/iceberg","slug":"e-message-rethrown-as-parse-error-with-command-co","errorCode":null,"errorMessage":"e.message (rethrown as parse error with command context)","messagePattern":"e\\.message \\(rethrown as parse error with command context\\)","errorType":"exception","errorClass":"IcebergParseException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSparkSqlExtensionsParser.scala","lineNumber":207,"sourceCode":"      } catch {\n        case _: ParseCancellationException =>\n          // if we fail, parse with LL mode with DefaultErrorStrategy\n          tokenStream.seek(0) // rewind input stream\n          parser.reset()\n\n          // Try Again.\n          parser.setErrorHandler(new DefaultErrorStrategy)\n          parser.getInterpreter.setPredictionMode(PredictionMode.LL)\n          toResult(parser)\n      }\n    } catch {\n      case e: IcebergParseException if e.command.isDefined =>\n        throw e\n      case e: IcebergParseException =>\n        throw e.withCommand(command)\n      case e: AnalysisException =>\n        val position = Origin(e.line, e.startPosition)\n        throw new IcebergParseException(Option(command), e.message, position, position)\n    }\n  }\n\n  override def parseQuery(sqlText: String): LogicalPlan = {\n    parsePlan(sqlText)\n  }\n}\n\nobject IcebergSparkSqlExtensionsParser {\n  private val substitutorCtor: DynConstructors.Ctor[VariableSubstitution] =\n    DynConstructors\n      .builder()\n      .impl(classOf[VariableSubstitution])\n      .impl(classOf[VariableSubstitution], classOf[SQLConf])\n      .build()\n}\n\n/* Copied from Apache Spark's to avoid dependency on Spark Internals */","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark-extensions/src/main/scala/org/apache/spark/sql/catalyst/parser/extensions/IcebergSparkSqlExtensionsParser.scala#L189-L225","documentation":"When plan parsing fails, this catch block rethrows the underlying error: IcebergParseErrors keep their original command context, other IcebergParseExceptions get the current command attached, and plain AnalysisExceptions are converted into an IcebergParseException carrying the SQL command and error position. It surfaces the underlying e.message enriched with the command being parsed.","triggerScenarios":"Calling parsePlan/parseQuery with SQL that triggers an analysis or Iceberg parse failure inside the extensions parser — e.g. malformed MERGE/ALTER statements or expressions failing analysis mid-parse.","commonSituations":"Submitting invalid Iceberg SQL extensions syntax through Spark; mismatched grammar between Spark and Iceberg extension versions.","solutions":["Fix the SQL syntax or semantic issue reported in e.message — the error reflects a real problem in the parsed statement","Verify Spark and Iceberg versions are compatible (grammar files must match the Spark minor version)","Run the failing statement through the appropriate Iceberg grammar docs to confirm supported syntax"],"exampleFix":"// before (ambiguous/unsupported syntax)\nALTER TABLE t WRITE ORDERED BY;\n// after\nALTER TABLE t WRITE ORDERED BY id;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  parser.parsePlan(sqlText)\n} catch {\n  case e: IcebergParseException =>\n    log.error(s\"Failed parsing command: ${e.getMessage}\"); throw e\n}","preventionTips":["Validate SQL against the Iceberg extension grammar before submitting","Keep Spark and Iceberg extension jars version-aligned","Log the full command text when parse errors occur"],"tags":["spark","parser","sql"],"backgroundTag":"invalid-argument-format","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"}