{"record":{"id":"73c1a12476bc0c7c","repo":"spring-projects/spring-ai","slug":"failed-to-delete-nodes-by-filter","errorCode":null,"errorMessage":"Failed to delete nodes by filter","messagePattern":"Failed to delete nodes by filter","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java","lineNumber":271,"sourceCode":"\t\t\tString whereClause = this.filterExpressionConverter.convertExpression(filterExpression);\n\n\t\t\t// Create Cypher query with transaction batching\n\t\t\tString cypher = \"\"\"\n\t\t\t\t\tMATCH (node:%s) WHERE %s\n\t\t\t\t\tCALL { WITH node DETACH DELETE node } IN TRANSACTIONS OF $transactionSize ROWS\n\t\t\t\t\t\"\"\".formatted(this.label, whereClause);\n\n\t\t\tvar summary = session.run(cypher, Map.of(\"transactionSize\", DEFAULT_TRANSACTION_SIZE)).consume();\n\n\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\tlogger.debug(\"Deleted \" + summary.counters().nodesDeleted() + \" nodes matching filter expression\");\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tif (logger.isErrorEnabled()) {\n\t\t\t\tlogger.error(\"Failed to delete nodes by filter: \" + e.getMessage(), e);\n\t\t\t}\n\t\t\tthrow new IllegalStateException(\"Failed to delete nodes by filter\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<Document> doSimilaritySearch(SearchRequest request) {\n\t\tAssert.isTrue(request.getTopK() > 0, \"The number of documents to returned must be greater than zero\");\n\t\tAssert.isTrue(request.getSimilarityThreshold() >= 0 && request.getSimilarityThreshold() <= 1,\n\t\t\t\t\"The similarity score is bounded between 0 and 1; least to most similar respectively.\");\n\n\t\tvar embedding = Values.value(this.embeddingModel.embed(request.getQuery()));\n\t\ttry (var session = this.driver.session(this.sessionConfig)) {\n\t\t\tStringBuilder condition = new StringBuilder(\"score >= $threshold\");\n\t\t\tif (request.hasFilterExpression()) {\n\t\t\t\tAssert.state(request.getFilterExpression() != null, \"filter expression can't be null\");\n\t\t\t\tcondition.append(\" AND \")\n\t\t\t\t\t.append(this.filterExpressionConverter.convertExpression(request.getFilterExpression()));\n\t\t\t}\n\t\t\tString query = \"\"\"","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java#L253-L289","documentation":"Neo4jVectorStore.doDelete wraps any exception thrown while executing the Cypher node-deletion (by id list or by filter expression) in an IllegalStateException with this message. It is a defensive wrapper so callers get a uniform runtime exception; the original cause is attached as the cause and also logged. The failure almost always originates in the Neo4j driver, Cypher syntax, or schema/constraint problems.","triggerScenarios":"Calling VectorStore.delete(List<String> idList) or delete(Filter.Expression) / delete(String filterExpression) on a Neo4jVectorStore when the Neo4j database is unreachable, the Cypher generated from the filter expression fails, or the session/transaction errors.","commonSituations":"Neo4j browser not running or wrong bolt URL in config; invalid filter expression string producing bad Cypher; deleted/renamed node labels or properties; Neo4j authentication failure; transient network drop during delete.","solutions":["Inspect the chained cause (e.getCause()) and the logged 'Failed to delete nodes by filter' stack trace for the underlying driver/Cypher error.","Verify Neo4j connectivity and credentials in the store configuration (uri, username, password).","Validate the filter expression syntax; test it against Filter.ExpressionBuilder or run the resulting Cypher manually in the Neo4j browser.","Confirm the configured label/embedding property names match the actual Neo4j schema."],"exampleFix":"// before\ndelete(\"country == 'IN' AND age IN [18,25]\"); // typo in filter leads to bad Cypher\n// after\ndelete(new Filter.Expression(AND, new Eq(\"country\", \"IN\"), new In(\"age\", List.of(18, 25))));","handlingStrategy":"try-catch","validationCode":"// before delete\ntry (Driver driver = GraphDatabase.driver(uri, AuthTokens.basic(user, pass))) {\n    driver.verifyConnectivity(); // fail fast if Neo4j is unreachable\n}","typeGuard":null,"tryCatchPattern":"try {\n    vectorStore.delete(idList);\n} catch (IllegalStateException e) {\n    logger.error(\"Neo4j delete failed: {}\", e.getCause() != null ? e.getCause().getMessage() : e.getMessage(), e);\n}","preventionTips":["Verify Neo4j connectivity at startup with driver.verifyConnectivity()","Test filter expressions against the converter before calling delete","Keep label/property configuration in sync with the actual Neo4j schema","Wrap delete calls in retry with backoff for transient network errors"],"tags":["neo4j","vector-store","delete","database"],"backgroundTag":"database-query-failed","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}