{"record":{"id":"d451748348daa446","repo":"apache/iceberg","slug":"unable-to-parse-sortorder-s","errorCode":null,"errorMessage":"Unable to parse sortOrder: %s","messagePattern":"Unable to parse sortOrder: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/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/v3.5/spark/src/main/java/org/apache/iceberg/spark/ExtendedParser.java#L45-L81","documentation":"ExtendedParser.parseSortOrder delegates order-string parsing to Spark's SQL parser when it is an Iceberg ExtendedParser; if the parser raises AnalysisException the string is unparseable and it rethrows IllegalArgumentException('Unable to parse sortOrder: %s'). Used by ALTER TABLE ... WRITE ORDERED BY / ADD SORT ORDER style flows.","triggerScenarios":"Passing an invalid sort-order expression string (bad syntax, unknown transform like 'truncatebad(10, col)', nonexistent column, unsupported expression) to API/SQL that parses a sort order string.","commonSituations":"Handwritten sort strings with typos; transforms not supported by the Spark parser version; using a column that doesn't exist in the schema; copying Hive/other-engine ORDER BY syntax Iceberg doesn't accept.","solutions":["Fix the sort-order expression syntax: valid form e.g. 'id ASC NULLS FIRST, truncate(10, name) DESC' with existing columns and Iceberg transforms.","Validate column names against the table schema before submitting the order string.","Verify the Spark session's SQL parser is the default SparkSQLParser (Iceberg's ExtendedParser wraps it); custom parser plugins can break detection.","Test the expression interactively with a simple ALTER TABLE ... WRITE ORDERED BY before embedding it in automation."],"exampleFix":"// before\nTableUtil.sortOrder(spark, table, \"id asc nulls last, foo(10, name)\");\n// after\nTableUtil.sortOrder(spark, table, \"id ASC NULLS FIRST, truncate(10, name) DESC\");","handlingStrategy":"validation","validationCode":"Set<String> validCols = table.schema().columns().stream().map(Types.NestedField::name).collect(Collectors.toSet());\n// every field referenced in orderString must be in validCols; transforms limited to identity,bucket,truncate,year,month,day,hour","typeGuard":null,"tryCatchPattern":"try { orders = ExtendedParser.parseSortOrder(spark, orderString); } catch (IllegalArgumentException e) { throw new UserInputException(\"Bad sort order: \" + orderString, e); }","preventionTips":["Validate columns and transforms in sort strings against the table schema before submit","Use canonical syntax: col ASC/DESC, NULLS FIRST/LAST, Iceberg transforms only","Verify the session parser supports ExtendedParser (see 2397) before string parsing"],"tags":["spark","sort-order","parse-error"],"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"}