{"record":{"id":"6166bde3fb7aab3c","repo":"apache/iceberg","slug":"unable-to-parse-sortorder-s-6166bd","errorCode":null,"errorMessage":"Unable to parse sortOrder: %s","messagePattern":"Unable to parse sortOrder: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/ExtendedParser.java","lineNumber":63,"sourceCode":"      return term;\n    }\n\n    public SortDirection direction() {\n      return direction;\n    }\n\n    public NullOrder nullOrder() {\n      return nullOrder;\n    }\n  }\n\n  static List<RawOrderField> parseSortOrder(SparkSession spark, String orderString) {\n    ExtendedParser extParser = findParser(spark.sessionState().sqlParser(), ExtendedParser.class);\n    if (extParser != null) {\n      try {\n        return extParser.parseSortOrder(orderString);\n      } catch (AnalysisException e) {\n        throw new IllegalArgumentException(\n            String.format(\"Unable to parse sortOrder: %s\", orderString), e);\n      }\n    } else {\n      throw new IllegalStateException(\n          \"Cannot parse order: parser is not an Iceberg ExtendedParser\");\n    }\n  }\n\n  private static <T> T findParser(ParserInterface parser, Class<T> clazz) {\n    ParserInterface current = parser;\n    while (current != null) {\n      if (clazz.isInstance(current)) {\n        return clazz.cast(current);\n      }\n\n      current = getNextDelegateParser(current);\n    }\n","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/ExtendedParser.java#L45-L81","documentation":"ExtendedParser.parseSortOrder delegates sort-order text to the Iceberg ExtendedParser SQL parser and wraps any resulting AnalysisException in this IllegalArgumentException. It means the supplied ORDER BY-style sort expression (e.g. for a write sort order) is not valid syntax. The original AnalysisException is chained as the cause.","triggerScenarios":"Calling SparkUtil/ExtendedParser.parseSortOrder(spark, orderString) with malformed SQL such as `id DESC NULLS LASTZ`, invalid transforms, or expressions the parser rejects; passing a bad 'sort-order' string via write options or table properties APIs.","commonSituations":"Copy-pasted sort expressions with typos; engine-version-specific syntax unsupported by the installed Spark parser; programmatically assembled SQL fragments that are invalid.","solutions":["Correct the sort-order string: it must be valid Spark SQL ORDER BY syntax (columns, Iceberg transforms like truncate(10, col), ASC/DESC, NULLS FIRST/LAST).","Reproduce the expression in `spark.sql(\"SELECT * FROM t ORDER BY <expr>\")` to see the precise chained AnalysisException message.","Confirm the session parser is the Iceberg ExtendedParser (see the companion IllegalStateException error) by configuring the Iceberg extensions."],"exampleFix":"// before\nString order = \"id DESC NULLS LASTZ\";\n// after\nString order = \"id DESC NULLS LAST\";","handlingStrategy":"validation","validationCode":"// dry-run the sort expression before using it\ntry {\n  spark.sql(\"SELECT * FROM t ORDER BY \" + orderString).queryExecution().analyzed();\n} catch (AnalysisException e) {\n  throw new IllegalArgumentException(\"Invalid sort order: \" + orderString, e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  SortOrder order = ExtendedParser.parseSortOrder(spark, orderString);\n} catch (IllegalArgumentException e) {\n  logger.error(\"Bad sort order: {}\", e.getCause() != null ? e.getCause().getMessage() : e.getMessage());\n}","preventionTips":["Test sort-order strings in spark.sql() before wiring them into table properties.","Use only documented syntax: columns, Iceberg transforms, ASC/DESC, NULLS FIRST/LAST.","Log the chained AnalysisException cause for the precise syntax error."],"tags":["spark","sql-parsing","sort-order"],"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"}