{"record":{"id":"78addaf1a039aae1","repo":"spring-projects/spring-ai","slug":"not-allowed-filter-identifier-name-78adda","errorCode":null,"errorMessage":"Not allowed filter identifier name: ","messagePattern":"Not allowed filter identifier name: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-typesense-store/src/main/java/org/springframework/ai/vectorstore/typesense/TypesenseFilterExpressionConverter.java","lineNumber":71,"sourceCode":"\t\t};\n\t}\n\n\t@Override\n\tprotected void doGroup(Filter.Group group, StringBuilder context) {\n\t\tthis.convertOperand(new Filter.Expression(Filter.ExpressionType.AND, group.content(), group.content()),\n\t\t\t\tcontext); // trick\n\t}\n\n\t@Override\n\tprotected void doKey(Filter.Key key, StringBuilder context) {\n\t\tvar identifier = (hasOuterQuotes(key.key())) ? removeOuterQuotes(key.key()) : key.key();\n\t\t// Typesense field names are bare identifiers in filter_by syntax\n\t\t// (field_name:value) with no escaping mechanism. Validate that the\n\t\t// identifier contains only safe characters to prevent filter injection.\n\t\tfor (int i = 0; i < identifier.length(); i++) {\n\t\t\tchar c = identifier.charAt(i);\n\t\t\tif (!Character.isLetterOrDigit(c) && c != '_' && c != '.' && c != '-') {\n\t\t\t\tthrow new IllegalArgumentException(\"Not allowed filter identifier name: \" + identifier);\n\t\t\t}\n\t\t}\n\t\tcontext.append(\"metadata.\").append(identifier).append(\":\");\n\t}\n\n\t/**\n\t * Serialize values using JSON serialization for Typesense filter expressions.\n\t * Delegates to {@link #emitJsonValue(Object, StringBuilder)} for Jackson-based JSON\n\t * serialization.\n\t * @param value the value to serialize\n\t * @param context the context to append the JSON representation to\n\t */\n\t@Override\n\tprotected void doSingleValue(Object value, StringBuilder context) {\n\t\temitJsonValue(value, context);\n\t}\n\n}","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-typesense-store/src/main/java/org/springframework/ai/vectorstore/typesense/TypesenseFilterExpressionConverter.java#L53-L89","documentation":"Typesense filter_by field names are bare identifiers (field_name:value) with no escaping mechanism, so doKey validates that the metadata key contains only letters, digits, '_', '.', and '-'. Any other character (spaces, quotes, parentheses, etc.) triggers this IllegalArgumentException, which also prevents filter injection through crafted key names.","triggerScenarios":"Running a similaritySearch or delete-by-filter with a Key metadata identifier containing characters outside [A-Za-z0-9_.-], e.g. 'user name', 'price$usd', or a key containing ':' or '\"'.","commonSituations":"Documents stored with metadata keys containing spaces or special characters; dynamically building keys from user input without sanitizing; migrating from stores that allowed arbitrary key names.","solutions":["Rename the metadata key in your documents to use only letters, digits, '_', '.', '-' (e.g. 'user_name').","Sanitize/validate identifier strings before embedding them into Filter expressions (e.g. replace invalid characters).","Validate user-supplied field names against a whitelist before constructing filter expressions."],"exampleFix":"// before\nvar expr = new Filter.Expression(EQ, new Key(\"user name\"), new Value(\"alice\"));\n// after\nvar expr = new Filter.Expression(EQ, new Key(\"user_name\"), new Value(\"alice\"));","handlingStrategy":"validation","validationCode":"if (!key.matches(\"[A-Za-z0-9_.-]+\")) throw new IllegalArgumentException(\"Illegal Typesense filter key: \" + key);","typeGuard":null,"tryCatchPattern":"try { vectorStore.similaritySearch(req); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Not allowed filter identifier\")) { /* sanitize key and retry */ } else throw e; }","preventionTips":["Use only letters, digits, '_', '.', '-' in metadata keys for Typesense","Sanitize user-supplied field names before building filters","Standardize document metadata key naming (e.g. camelCase or snake_case) at ingestion time"],"tags":["vector-store","filter-expression","typesense","identifier-validation","injection-prevention"],"backgroundTag":"invalid-identifier-format","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}