{"record":{"id":"068381eedd48d951","repo":"apache/beam","slug":"error-writing-unwindlist-size-rows-to-neo4j-with-cypher","errorCode":null,"errorMessage":"Error writing \" + unwindList.size() + \" rows to Neo4j with Cypher: \" + cypher","messagePattern":"Error writing \" \\+ unwindList\\.size\\(\\) \\+ \" rows to Neo4j with Cypher: \" \\+ cypher","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/neo4j/src/main/java/org/apache/beam/sdk/io/neo4j/Neo4jIO.java","lineNumber":1186,"sourceCode":"            return null;\n          };\n\n      if (logCypher && !loggingDone) {\n        String parametersString = getParametersString(parametersMap);\n        LOG.info(\n            \"Starting a write transaction for unwind statement cypher: {}, parameters: {}\",\n            cypher,\n            parametersString);\n        loggingDone = true;\n      }\n\n      if (driverSession.session == null) {\n        throw new RuntimeException(\"neo4j session was not initialized correctly\");\n      } else {\n        try {\n          driverSession.session.writeTransaction(transactionWork, transactionConfig);\n        } catch (Exception e) {\n          throw new RuntimeException(\n              \"Error writing \" + unwindList.size() + \" rows to Neo4j with Cypher: \" + cypher, e);\n        }\n      }\n\n      // Now we need to reset the number of elements read and the parameters map\n      //\n      unwindList.clear();\n      elementsInput = 0;\n    }\n\n    @FinishBundle\n    @Override\n    public void finishBundle() {\n      executeCypherUnwindStatement();\n    }\n  }\n}\n","sourceCodeStart":1168,"sourceCodeEnd":1204,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/neo4j/src/main/java/org/apache/beam/sdk/io/neo4j/Neo4jIO.java#L1168-L1204","documentation":"When session.writeTransaction(...) throws while flushing a UNWIND batch, WriteUnwindFn wraps the exception in a RuntimeException that includes the batch size and the Cypher statement, preserving the cause. This tells you the write transaction itself failed (query error, constraint violation, connectivity, transient cluster issues).","triggerScenarios":"Neo4j rejects the transaction: Cypher syntax error, constraint violation (e.g. unique constraint on unwound rows), deadlock/transient errors, connection loss mid-write, or statement exceeding limits.","commonSituations":"Duplicate-key violations when batching with UNWIND into uniquely-constrained nodes; oversized batches timing out; schema changes making the Cypher invalid; network blips between Beam workers and the Neo4j cluster.","solutions":["Read the cause (getCause) for the actual Neo4j error and fix the Cypher/constraint accordingly.","Reduce the unwind batch size / add retry with backoff for transient (TransientException) failures.","Validate rows before writing to avoid constraint violations (e.g. MERGE instead of CREATE for idempotent writes)."],"exampleFix":"// before\nUNWIND $rows AS row CREATE (n:Person {id: row.id})\n// constraint violations on rerun\n// after\nUNWIND $rows AS row MERGE (n:Person {id: row.id}) SET n.name = row.name","handlingStrategy":"retry","validationCode":"// Pre-validate rows against constraints in a dry-run batch if possible.","typeGuard":null,"tryCatchPattern":"try { session.writeTransaction(txWork, config); } catch (TransientException te) { retryWithBackoff(); } catch (Exception e) { throw new RuntimeException(\"Error writing batch\", e); }","preventionTips":["Use MERGE for idempotent writes under unique constraints.","Keep unwind batches small; tune max batch size and transaction timeout.","Inspect getCause() for the real Neo4j error code."],"tags":["java","neo4j","apache-beam","database-write"],"backgroundTag":"database-write-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}