{"record":{"id":"b37aa8d053a49739","repo":"alibaba/canal","slug":"requestpost-remote-error-request-statuscode","errorCode":null,"errorMessage":"requestPost remote error, request : {}, statusCode={};{}","messagePattern":"requestPost remote error, request : (.+?), statusCode=(.+?);(.+?)","errorType":"http","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain/HttpHelper.java","lineNumber":147,"sourceCode":"            httpPost = new HttpPost(uri);\n            StringEntity entity = new StringEntity(requestBody, \"UTF-8\");\n            httpPost.setEntity(entity);\n            httpPost.setHeader(\"Content-Type\", \"application/json;charset=utf8\");\n            if (heads != null) {\n                for (Map.Entry<String, String> entry : heads.entrySet()) {\n                    httpPost.setHeader(entry.getKey(), entry.getValue());\n                }\n            }\n\n            HttpClientContext context = HttpClientContext.create();\n            context.setRequestConfig(config);\n\n            response = httpclient.execute(httpPost, context);\n            int statusCode = response.getStatusLine().getStatusCode();\n            if (statusCode == HttpStatus.SC_OK) {\n                return EntityUtils.toString(response.getEntity());\n            } else {\n                throw new RuntimeException(\"requestPost remote error, request : \" + url + \", statusCode=\" + statusCode\n                                           + \";\" + EntityUtils.toString(response.getEntity()));\n            }\n        } catch (Throwable t) {\n            throw new RuntimeException(\"requestPost remote error, request : \" + url, t);\n        } finally {\n            if (response != null) {\n                try {\n                    response.close();\n                } catch (IOException e) {\n                    // ignore\n                }\n            }\n            if (httpPost != null) {\n                httpPost.releaseConnection();\n            }\n        }\n    }\n","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain/HttpHelper.java#L129-L165","documentation":"Inner throw in HttpHelper.post0() (HttpHelper.java:147-148): fired when the HTTP POST response status is not 200 OK. Builds RuntimeException 'requestPost remote error, request : <url>, statusCode=<statusCode>;<response body>'. As with the GET path, this throw is inside the try block whose catch(Throwable t) at line 150-151 immediately re-wraps it into a NEW RuntimeException ('requestPost remote error, request : <url>', originalException-as-cause). Callers only see the outer message (error 359); the line-147 message is preserved as the cause.","triggerScenarios":"HttpHelper.post/post0 returning a non-200 status — typically when posting instance config updates/heartbeats to canal-manager and the manager responds with an error code. The response body is concatenated after the statusCode in the message, then re-wrapped by the outer catch.","commonSituations":"Manager auth token invalid/expired (401/50014); malformed JSON body → 400; manager-side validation failure (500); endpoint not registered (404); conflicting/unchanged config update rejected; rate limiting.","solutions":["Unwrap getCause() on the RuntimeException reaching the caller — its message contains 'statusCode=...' plus the response body from line 147.","Fix per status: 401/50014 → refresh the manager token; 400 → validate the JSON body being posted; 404 → correct the manager REST path; 500 → inspect manager logs.","Reproduce with curl -X POST -H 'Content-Type: application/json' -d '<body>' <url> using the same headers to see the manager's error response directly.","Ensure the request body is serializable via fastjson2 (post() calls JSON.toJSONString(requestBody)) — a serialization error throws before the request is sent and is caught by the same outer handler."],"exampleFix":"// before — only the outer message is visible\ntry {\n    helper.post(url, heads, payload, timeout);\n} catch (RuntimeException e) {\n    log.error(e.getMessage()); // 'requestPost remote error, request : <url>'\n}\n\n// after — read the cause for statusCode + body\ntry {\n    helper.post(url, heads, payload, timeout);\n} catch (RuntimeException e) {\n    Throwable cause = e.getCause();\n    if (cause != null && cause.getMessage() != null\n        && cause.getMessage().contains(\"statusCode=\")) {\n        log.error(\"manager POST rejected: {}\", cause.getMessage());\n    } else {\n        log.error(\"manager POST failed\", e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Ensure the payload serializes cleanly before posting (post() calls JSON.toJSONString)\ntry {\n    String json = JSON.toJSONString(requestBody);\n    if (StringUtils.isBlank(json)) {\n        throw new IllegalArgumentException(\"requestBody serializes to empty JSON\");\n    }\n} catch (Exception e) {\n    throw new IllegalArgumentException(\"requestBody is not JSON-serializable\", e);\n}","typeGuard":null,"tryCatchPattern":"// The inner throw is re-wrapped; read getCause() for statusCode + response body\ntry {\n    String body = helper.post(url, heads, payload, timeout);\n} catch (RuntimeException e) {\n    Throwable cause = e.getCause();\n    if (cause != null && cause.getMessage() != null && cause.getMessage().contains(\"statusCode=\")) {\n        log.error(\"manager POST rejected: {}\", cause.getMessage());\n    } else {\n        log.error(\"manager POST failed\", e);\n    }\n    throw e;\n}","preventionTips":["Unwrap getCause() to read the statusCode and response body from line 147.","Refresh manager tokens proactively to avoid 401/50014 on POST.","Pre-serialize payloads with fastjson2 to catch serialization errors before they hit the network.","Reproduce failures with curl -X POST -H 'Content-Type: application/json' -d '<json>' <url>."],"tags":["http","manager-client","rest","post","runtime-exception","error-wrapping"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}