{"record":{"id":"108b943a1793b222","repo":"apache/iceberg","slug":"cannot-parse-s-s","errorCode":null,"errorMessage":"Cannot parse %s: %s","messagePattern":"Cannot parse (.+?): (.+?)","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java","lineNumber":776,"sourceCode":"      SparkSession spark, String name, CatalogPlugin defaultCatalog) throws ParseException {\n    ParserInterface parser = spark.sessionState().sqlParser();\n    Seq<String> multiPartIdentifier = parser.parseMultipartIdentifier(name).toIndexedSeq();\n    List<String> javaMultiPartIdentifier = JavaConverters.seqAsJavaList(multiPartIdentifier);\n    return catalogAndIdentifier(spark, javaMultiPartIdentifier, defaultCatalog);\n  }\n\n  public static CatalogAndIdentifier catalogAndIdentifier(\n      String description, SparkSession spark, String name) {\n    return catalogAndIdentifier(\n        description, spark, name, spark.sessionState().catalogManager().currentCatalog());\n  }\n\n  public static CatalogAndIdentifier catalogAndIdentifier(\n      String description, SparkSession spark, String name, CatalogPlugin defaultCatalog) {\n    try {\n      return catalogAndIdentifier(spark, name, defaultCatalog);\n    } catch (ParseException e) {\n      throw new IllegalArgumentException(\"Cannot parse \" + description + \": \" + name, e);\n    }\n  }\n\n  public static CatalogAndIdentifier catalogAndIdentifier(\n      SparkSession spark, List<String> nameParts) {\n    return catalogAndIdentifier(\n        spark, nameParts, spark.sessionState().catalogManager().currentCatalog());\n  }\n\n  /**\n   * A modified version of Spark's LookupCatalog.CatalogAndIdentifier.unapply Attempts to find the\n   * catalog and identifier a multipart identifier represents\n   *\n   * @param spark Spark session to use for resolution\n   * @param nameParts Multipart identifier representing a table\n   * @param defaultCatalog Catalog to use if none is specified\n   * @return The CatalogPlugin and Identifier for the table\n   */","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/Spark3Util.java#L758-L794","documentation":"Spark3Util.catalogAndIdentifier(description, ...) parses an identifier string using Spark's parser and rethrows ParseException as IllegalArgumentException 'Cannot parse <description>: <name>'. The description (e.g. 'namespace' or 'identifier') indicates what failed to parse.","triggerScenarios":"Calling Spark3Util.catalogAndIdentifier(spark, name, defaultCatalog) (or the description overload) with a name that Spark's ParserInterface cannot parse — typically names with invalid characters, backticks misuse, or unbalanced quotes.","commonSituations":"Passing user-supplied table/namespace strings with special characters (dots, backticks, quotes) into procedures like CALL catalog.system.* actions or extension code that resolves identifiers.","solutions":["Quote problematic identifier parts with backticks and escape embedded backticks before passing the name","Validate/sanitize the name (reject or escape reserved characters) before calling catalogAndIdentifier","Call catalogAndIdentifier(List<String> nameParts) with pre-split parts to bypass the string parser entirely"],"exampleFix":"// before\nSpark3Util.catalogAndIdentifier(spark, \"my.table\\\"name\", defaultCatalog); // throws\n// after\nSpark3Util.catalogAndIdentifier(spark, Arrays.asList(\"my\", \"table\\\"name\"), defaultCatalog);","handlingStrategy":"validation","validationCode":"if (!name.matches(\"[a-zA-Z0-9_.`]+\")) throw new IllegalArgumentException(\"Invalid identifier: \" + name);","typeGuard":null,"tryCatchPattern":"try { return Spark3Util.catalogAndIdentifier(desc, spark, name, defaultCatalog); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(\"Bad \" + desc + \" name: \" + name, e); }","preventionTips":["Pre-split identifiers into name parts and use the List<String> overload","Escape backticks and quotes in user-supplied names","Validate identifiers at API boundaries before passing to Spark parsing"],"tags":["spark","identifier","parsing"],"backgroundTag":"invalid-identifier-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"}