{"record":{"id":"d5cde2ae5cf7495c","repo":"apache/seatunnel","slug":"multi-table-sink-encountered-non-row-level-error-i","errorCode":null,"errorMessage":"Multi-table sink encountered non-row-level error in plugin [{}], table [{}]: {}","messagePattern":"Multi-table sink encountered non-row-level error in plugin \\[(.+?)\\], table \\[(.+?)\\]: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/EngineMultiTableRowErrorHandler.java","lineNumber":75,"sourceCode":"            RowErrorClassifier<SeaTunnelRow> rowErrorClassifier,\n            String pluginName,\n            BiConsumer<SeaTunnelRow, ErrorHandlingSinkWriter.WriteOutcome> outcomeConsumer,\n            EngineRowErrorCollector rowErrorCollector) {\n        this.errorHandler = errorHandler;\n        this.rowErrorClassifier = rowErrorClassifier;\n        this.pluginName = pluginName;\n        this.outcomeConsumer = outcomeConsumer;\n        this.rowErrorCollector = rowErrorCollector;\n    }\n\n    @Override\n    public boolean handleRowError(\n            SinkWriter<SeaTunnelRow, ?, ?> writer, String tableId, SeaTunnelRow row, Throwable t) {\n        String effectiveTableId = tableId != null ? tableId : resolveTableId(row);\n\n        if (!isRowError(writer, row, t)) {\n            // System-level error: let caller treat it as fatal.\n            log.warn(\n                    \"Multi-table sink encountered non-row-level error in plugin [{}], table [{}]: {}\",\n                    pluginName,\n                    effectiveTableId,\n                    t != null ? t.getMessage() : null,\n                    t);\n            return false;\n        }\n\n        RowErrorContext ctx = new RowErrorContext(\"SINK\", \"SINK\", pluginName, effectiveTableId);\n\n        // Delegate to shared ErrorHandler; it may throw when thresholds or queue policies demand\n        // a job failure.\n        log.debug(\n                \"Routing multi-table row-level error to error handler for plugin [{}], table [{}]: {}\",\n                pluginName,\n                effectiveTableId,\n                t != null ? t.getMessage() : null);\n        ErrorHandler.ErrorHandleResult result = errorHandler.onError(ctx, row, t);","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/EngineMultiTableRowErrorHandler.java#L57-L93","documentation":"EngineMultiTableRowErrorHandler.handleRowError classifies sink exceptions as row-level (skippable) or system-level (fatal). When isRowError() returns false, this warning is logged with plugin and table context and the handler returns false, telling the caller to treat the error as fatal. It means a write failure occurred that the error-handling policy does not consider safe to skip per-row.","triggerScenarios":"A multi-table sink write throws an exception not classified as a row error (e.g. connection loss, serialization failure of the whole batch, null writer, generic RuntimeException/SQLException not in the row-error categories), with row error handling enabled.","commonSituations":"Error-sink/target database outage during a run; batch-level failures where individual rows cannot be identified; misconfigured error handler expecting all failures to be skippable; connector throwing wrapper exceptions not recognized by isRowError.","solutions":["Read the chained cause: fix the underlying system-level issue (connectivity, permissions, schema) and rerun.","If the exception is genuinely row-scoped but misclassified, upgrade/patch the connector's exception classification.","Adjust job design so system-level failures are retried rather than skipped — do not force these to be skippable.","If too many such warnings appear, check whether the error-handling config (row vs system errors) matches the connector's behavior."],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"boolean handled = rowErrorHandler.handleRowError(writer, tableId, row, t);\nif (!handled) {\n    // system-level failure: rethrow as fatal\n    throw new RuntimeException(\"Non-row-level sink error in \" + tableId, t);\n}","preventionTips":["Monitor error-sink/target DB availability","Classify connector exceptions correctly so row-scoped failures are not treated as system-level","Set up retry for system-level errors instead of expecting them to be skipped"],"tags":["error-handling","multi-table-sink","fatal-error"],"backgroundTag":"row-error-classification","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}