{"record":{"id":"d6fa0664f15880a6","repo":"apache/seatunnel","slug":"error-sink-previously-failed-for-stage-s-plugi","errorCode":null,"errorMessage":"Error sink previously failed for stage [%s], plugin [%s]","messagePattern":"Error sink previously failed for stage \\[(.+?)\\], plugin \\[(.+?)\\]","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/DefaultErrorSinkWriter.java","lineNumber":146,"sourceCode":"    /** Initializes the child sink and worker thread during task startup. */\n    public void open() {\n        ensureInitialized();\n    }\n\n    @Override\n    public void write(RowErrorContext ctx, T row, Throwable t) throws Exception {\n        writeAndCheckAccepted(ctx, row, t);\n    }\n\n    @Override\n    public boolean writeAndCheckAccepted(RowErrorContext ctx, T row, Throwable t) throws Exception {\n        if (stageConfig.getMode() != ErrorHandlerMode.ROUTE) {\n            return false;\n        }\n        ensureInitialized();\n\n        if (workerFailure != null) {\n            throw new RuntimeException(\n                    String.format(\n                            \"Error sink previously failed for stage [%s], plugin [%s]\",\n                            ctx.getStage(), ctx.getPluginName()),\n                    workerFailure);\n        }\n\n        SeaTunnelRow errorRow = buildErrorRow(ctx, row, t);\n\n        try {\n            switch (stageConfig.getQueueOverflowPolicy()) {\n                case DROP:\n                    pendingRows.incrementAndGet();\n                    if (!queue.offer(errorRow)) {\n                        pendingRows.decrementAndGet();\n                        return false;\n                    }\n                    break;\n                case BLOCK:","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/DefaultErrorSinkWriter.java#L128-L164","documentation":"DefaultErrorSinkWriter.writeAndCheckAccepted throws this when a previous failure of the error-sink worker thread has been recorded (workerFailure != null) and a new error row is submitted to a ROUTE-mode error sink. The writer is in a permanently failed state: every subsequent write rethrows the original worker failure wrapped in a new RuntimeException so the caller knows the error sink is dead and no rows can be routed there anymore.","triggerScenarios":"The error-sink background worker thread threw an exception earlier (recorded in workerFailure), and afterwards write() -> writeAndCheckAccepted() is called again for stage ROUTE mode. The very next write after any worker crash hits this path.","commonSituations":"Error sink (e.g. configured console/jdbc error sink) crashed mid-job due to network outage or invalid credentials; job keeps producing error rows which now all fail with this wrapped exception; a deliberately failing test sink triggers it.","solutions":["Inspect the wrapped cause (workerFailure) to find why the error sink worker originally failed","Fix the underlying error sink problem (connectivity, schema, permissions) and restart/retry the job","Enable checkpoint/restart so the task is fully reinitialized instead of writing into a failed writer","If failure is transient, consider an ErrorHandlerMode other than ROUTE or add resilient error-sink config"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (errorSinkWriter.isFailed()) { /* reroute or restart before writing */ }","typeGuard":null,"tryCatchPattern":"try {\n    writer.write(row);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof Throwable && e.getMessage().contains(\"previously failed\")) {\n        LOG.error(\"Error sink already dead; original cause: \", e.getCause());\n        throw e;\n    }\n}","preventionTips":["Fix the first worker failure cause before retrying writes; the writer is permanently failed","Monitor error-sink worker health and restart the task rather than reusing a failed writer","Use resilient error sinks (local file/console) for ROUTE mode","Enable job-level restart from checkpoint"],"tags":["error-sink","route-mode","task-failure","zeta-engine"],"backgroundTag":"invalid-state-transition","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}