{"record":{"id":"3bc35032e4194653","repo":"apache/seatunnel","slug":"http-code-from-url-errorbody","errorCode":null,"errorMessage":"HTTP ${code} from ${url}: ${errorBody}","messagePattern":"HTTP (.+?) from (.+?): (.+?)","errorType":"http","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/LoggerLevelService.java","lineNumber":229,"sourceCode":"        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();\n        try {\n            connection.setRequestMethod(method);\n            connection.setConnectTimeout(REQUEST_TIMEOUT_MS);\n            connection.setReadTimeout(REQUEST_TIMEOUT_MS);\n            if (httpConfig.isEnableBasicAuth()) {\n                String credentials =\n                        httpConfig.getBasicAuthUsername() + \":\" + httpConfig.getBasicAuthPassword();\n                connection.setRequestProperty(\n                        \"Authorization\",\n                        \"Basic \"\n                                + Base64.getEncoder()\n                                        .encodeToString(\n                                                credentials.getBytes(StandardCharsets.UTF_8)));\n            }\n            connection.connect();\n            int code = connection.getResponseCode();\n            if (code != HttpURLConnection.HTTP_OK) {\n                throw new IOException(\n                        \"HTTP \" + code + \" from \" + url + \": \" + read(connection.getErrorStream()));\n            }\n            return Json.parse(read(connection.getInputStream())).asObject();\n        } finally {\n            connection.disconnect();\n        }\n    }\n\n    private JsonObject loggerJson(String name, Level level) {\n        JsonObject logger =\n                new JsonObject()\n                        .add(NAME, name)\n                        .add(LEVEL, level == null ? null : level.name())\n                        .add(ORIGIN, LogLevels.origin(name));\n        Level fileLevel = LogLevels.levelBeforeOverride(name);\n        if (fileLevel != null) {\n            logger.add(FILE_LEVEL, fileLevel.name());\n        }","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/LoggerLevelService.java#L211-L247","documentation":"LoggerLevelService.request performs an HTTP call to a remote node's log-level REST endpoint and throws an IOException whenever the response status is not 200, embedding the status code, the URL, and the error-stream body in the message. It is propagated by fanOut when aggregating log-level changes across cluster nodes, so a single unhealthy node surfaces this error.","triggerScenarios":"Changing or querying logger levels cluster-wide where any node answers with a non-200 status: 404 (node running an older version without the log-level endpoint), 401 (auth mismatch), 500 (node-side error), or connection to a wrong port/host.","commonSituations":"Rolling upgrades where some nodes lack the new log-level API; httpConfig port changed on some workers but not others; security/auth settings differing between nodes; a node in a crashed or overloaded state returning 5xx.","solutions":["Read the errorBody embedded in the message to identify the failing node and status; fix that node first.","Verify all nodes run the same SeaTunnel version and expose the log-level REST endpoint on the configured http port.","Check network/firewall and auth (basic credentials) consistency across the cluster.","Retry the operation once the offending node is healthy; fanOut errors are per-node and transient 5xx may succeed on retry."],"exampleFix":"// before\ncurl -X POST 'http://old-worker:8080/log-level' ...  -> 404 on upgraded-mixed cluster\n// after\n# upgrade all nodes, verify endpoint, then re-run cluster-wide level change\ncurl -X POST 'http://worker:8080/log-level?logger=root&level=WARN'","handlingStrategy":"retry","validationCode":"// pre-check each node before fan-out\nnodes.forEach(n => fetch(\"http://\" + n + \":\" + port + \"/health\") .then(r => { if (!r.ok) throw new Error(\"node \" + n + \" unhealthy: \" + r.status); }));","typeGuard":null,"tryCatchPattern":"try { fanOut(nodes, payload); } catch (IOException e) {\n  if (e.getMessage().matches(\"HTTP \\\\d+ .*\")) {\n    // parse code/url from message; retry transient 5xx, alert on 4xx\n    retryWithBackoff(excludingPersistentlyFailingNodes(e));\n  } else throw e;\n}","preventionTips":["Keep all cluster nodes on the same SeaTunnel version and HTTP port configuration.","Monitor node health before issuing cluster-wide log-level changes.","Apply log-level changes per node with per-node error handling instead of failing the whole fan-out."],"tags":["http","network","cluster","log-level"],"backgroundTag":"http-error-response","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"}