apache/beam · error · RuntimeException

Error writing " + unwindList.size() + " rows to Neo4j with…

Error message

Error writing " + unwindList.size() + " rows to Neo4j with Cypher: " + cypher

What it means

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).

Solutions

  1. Read the cause (getCause) for the actual Neo4j error and fix the Cypher/constraint accordingly.
  2. Reduce the unwind batch size / add retry with backoff for transient (TransientException) failures.
  3. Validate rows before writing to avoid constraint violations (e.g. MERGE instead of CREATE for idempotent writes).

Example fix

// before
UNWIND $rows AS row CREATE (n:Person {id: row.id})
// constraint violations on rerun
// after
UNWIND $rows AS row MERGE (n:Person {id: row.id}) SET n.name = row.name
Defensive patterns

Strategy: retry

Validate before calling

// Pre-validate rows against constraints in a dry-run batch if possible.

Try / catch

try { session.writeTransaction(txWork, config); } catch (TransientException te) { retryWithBackoff(); } catch (Exception e) { throw new RuntimeException("Error writing batch", e); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/068381eedd48d951. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/neo4j/src/main/java/org/apache/beam/sdk/io/neo4j/Neo4jIO.java:1186

            return null;
          };

      if (logCypher && !loggingDone) {
        String parametersString = getParametersString(parametersMap);
        LOG.info(
            "Starting a write transaction for unwind statement cypher: {}, parameters: {}",
            cypher,
            parametersString);
        loggingDone = true;
      }

      if (driverSession.session == null) {
        throw new RuntimeException("neo4j session was not initialized correctly");
      } else {
        try {
          driverSession.session.writeTransaction(transactionWork, transactionConfig);
        } catch (Exception e) {
          throw new RuntimeException(
              "Error writing " + unwindList.size() + " rows to Neo4j with Cypher: " + cypher, e);
        }
      }

      // Now we need to reset the number of elements read and the parameters map
      //
      unwindList.clear();
      elementsInput = 0;
    }

    @FinishBundle
    @Override
    public void finishBundle() {
      executeCypherUnwindStatement();
    }
  }
}

View on GitHub (pinned to 12126d8942)