{"record":{"id":"0f0f874de0ad6f17","repo":"apache/beam","slug":"quoted-identifier-cannot-contain-unescaped-quote","errorCode":null,"errorMessage":"quoted identifier cannot contain unescaped quote","messagePattern":"quoted identifier cannot contain unescaped quote","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/QueryUtils.java","lineNumber":262,"sourceCode":"        }\n      }\n      return Integer.compare(this.getSegments().size(), other.getSegments().size());\n    }\n\n    private static String unescapeFieldName(String fieldName) {\n      if (fieldName.isEmpty()) {\n        throw new IllegalArgumentException(\"quoted identifier cannot be empty\");\n      }\n      StringBuilder buf = new StringBuilder();\n      for (int i = 0; i < fieldName.length(); i++) {\n        char c = fieldName.charAt(i);\n        // Roughly speaking, there are 4 cases we care about:\n        //   - carriage returns: \\r and \\r\\n\n        //   - unescaped quotes: `\n        //   - non-escape sequences\n        //   - escape sequences\n        if (c == '`') {\n          throw new IllegalArgumentException(\"quoted identifier cannot contain unescaped quote\");\n        } else if (c == '\\r') {\n          buf.append('\\n');\n          // Convert '\\r\\n' into '\\n'\n          if (i + 1 < fieldName.length() && fieldName.charAt(i + 1) == '\\n') {\n            i++;\n          }\n        } else if (c != '\\\\') {\n          buf.append(c);\n        } else if (i + 1 >= fieldName.length()) {\n          throw new IllegalArgumentException(\"illegal trailing backslash\");\n        } else {\n          i++;\n          switch (fieldName.charAt(i)) {\n            case 'a':\n              buf.appendCodePoint(Ascii.BEL); // \"Alert\" control character\n              break;\n            case 'b':\n              buf.append('\\b');","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/QueryUtils.java#L244-L280","documentation":"unescapeFieldName() scans the inner content of a backtick-quoted identifier and throws this IllegalArgumentException if it encounters a bare backtick that is not escaped as \\`. Quoted Firestore identifiers must escape any backtick characters they contain.","triggerScenarios":"A backtick-quoted identifier whose content contains an unescaped ` character, e.g. fromString(\"a.`my`field`\") — the inner backtick terminates the quote in the outer regex but any surviving raw ` inside the unescaped content is rejected.","commonSituations":"Field names that themselves contain backticks (rare but possible in Firestore) configured without the required \\` escape; generated paths that concatenate identifiers without escaping.","solutions":["Escape every literal backtick inside the quoted segment as \\`","Escape backslashes too (\\) since they begin escape sequences","Prefer renaming the field to avoid backticks if you control the schema"],"exampleFix":"// before\nOrderByFieldPath.fromString(\"doc.`my`field`\");\n// after\nOrderByFieldPath.fromString(\"doc.`my\\\\`field`\");","handlingStrategy":"validation","validationCode":"public static String escapeQuotedIdentifier(String name) {\n  return \"`\" + name.replace(\"\\\\\", \"\\\\\\\\\").replace(\"`\", \"\\\\`\") + \"`\";\n}","typeGuard":null,"tryCatchPattern":"try {\n  OrderByFieldPath p = OrderByFieldPath.fromString(rawPath);\n} catch (IllegalArgumentException e) {\n  // retry with properly escaped segments\n}","preventionTips":["Always build quoted identifiers through an escaping helper, never raw string concatenation","Escape both backslashes and backticks inside quoted segments"],"tags":["java","apache-beam","firestore","field-path","escaping"],"backgroundTag":"invalid-identifier-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}