apache/seatunnel · error · Neo4jConnectorException

READER_OPERATION_FAILED

READER_OPERATION_FAILED

Error message

Failed to read Neo4j table '${tableId}'.

What it means

While reading a specific Neo4j table (executing its Cypher query via the driver), a RuntimeException occurred. readTable wraps it in Neo4jConnectorException with code READER_OPERATION_FAILED and includes the table id, preserving the original as cause. If tableId is null, the original exception propagates unchanged.

Solutions

  1. Read the cause of the Neo4jConnectorException for the actual driver/Cypher error.
  2. Validate the Cypher query directly against the Neo4j server (browser/shell).
  3. Check Neo4j availability, credentials, and query timeouts; increase driver timeout or add pagination for large results.

Example fix

// before
query = "MATCH (n:Persn) RETURN n.name AS name"
// after
query = "MATCH (n:Person) RETURN n.name AS name"
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate queries up front:
tables_configs.forEach(c -> driver.session().run("EXPLAIN " + c.getQuery()).consume());

Try / catch

try {
  readTable(tableConfig);
} catch (Neo4jConnectorException e) {
  log.error("table={} failed: {}", tableConfig.getTableId(), e.getCause());
  throw e;
}

Prevention

When it happens

Trigger: internalPollNext -> readTable executes the table's query with executeRead(tx -> ...); any RuntimeException from the driver (query syntax error, connection loss, timeout) is wrapped with "Failed to read Neo4j table '<tableId>'."

Common situations: Invalid Cypher syntax in tables_configs/root query; Neo4j server restart or network partition mid-read; auth/permission errors executing the query; driver timeouts on large result sets.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/e2e9ff226d05ee15. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-neo4j/src/main/java/org/apache/seatunnel/connectors/seatunnel/neo4j/source/Neo4jSourceReader.java:150

            this.context.signalNoMoreElement();
        }
    }

    private void readTable(Collector<SeaTunnelRow> output, Neo4jSourceTableConfig tableConfig) {
        final Query query = new Query(tableConfig.getQuery());
        try {
            session.readTransaction(
                    tx -> {
                        final Result result = tx.run(query);
                        result.stream()
                                .forEach(row -> output.collect(convertRecord(row, tableConfig)));
                        return null;
                    });
        } catch (RuntimeException exception) {
            if (tableConfig.getTableId() == null) {
                throw exception;
            }
            throw new Neo4jConnectorException(
                    CommonErrorCodeDeprecated.READER_OPERATION_FAILED,
                    "Failed to read Neo4j table '" + tableConfig.getTableId() + "'.",
                    exception);
        }
    }

    static SeaTunnelRow convertRecord(Record record, Neo4jSourceTableConfig tableConfig) {
        SeaTunnelRowType rowType = tableConfig.getRowType();
        Object[] fields = new Object[rowType.getTotalFields()];
        for (int i = 0; i < rowType.getTotalFields(); i++) {
            String fieldName = rowType.getFieldName(i);
            SeaTunnelDataType<?> fieldType = rowType.getFieldType(i);
            Value value = record.get(fieldName);
            fields[i] = convertType(fieldType, value);
        }
        SeaTunnelRow seaTunnelRow = new SeaTunnelRow(fields);
        if (tableConfig.getTableId() != null) {
            seaTunnelRow.setTableId(tableConfig.getTableId());

View on GitHub (pinned to cf67b549a7)