alibaba/canal · error · RuntimeException
requestPost remote error, request : {}, statusCode={};{}
Error message
requestPost remote error, request : {}, statusCode={};{} What it means
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.
Source
Thrown at instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain/HttpHelper.java:147
httpPost = new HttpPost(uri);
StringEntity entity = new StringEntity(requestBody, "UTF-8");
httpPost.setEntity(entity);
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
if (heads != null) {
for (Map.Entry<String, String> entry : heads.entrySet()) {
httpPost.setHeader(entry.getKey(), entry.getValue());
}
}
HttpClientContext context = HttpClientContext.create();
context.setRequestConfig(config);
response = httpclient.execute(httpPost, context);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
return EntityUtils.toString(response.getEntity());
} else {
throw new RuntimeException("requestPost remote error, request : " + url + ", statusCode=" + statusCode
+ ";" + EntityUtils.toString(response.getEntity()));
}
} catch (Throwable t) {
throw new RuntimeException("requestPost remote error, request : " + url, t);
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
// ignore
}
}
if (httpPost != null) {
httpPost.releaseConnection();
}
}
}
View on GitHub (pinned to 87be50e876)
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.
Example fix
// before — only the outer message is visible
try {
helper.post(url, heads, payload, timeout);
} catch (RuntimeException e) {
log.error(e.getMessage()); // 'requestPost remote error, request : <url>'
}
// after — read the cause for statusCode + body
try {
helper.post(url, heads, payload, timeout);
} catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause != null && cause.getMessage() != null
&& cause.getMessage().contains("statusCode=")) {
log.error("manager POST rejected: {}", cause.getMessage());
} else {
log.error("manager POST failed", e);
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure the payload serializes cleanly before posting (post() calls JSON.toJSONString)
try {
String json = JSON.toJSONString(requestBody);
if (StringUtils.isBlank(json)) {
throw new IllegalArgumentException("requestBody serializes to empty JSON");
}
} catch (Exception e) {
throw new IllegalArgumentException("requestBody is not JSON-serializable", e);
} Try / catch
// The inner throw is re-wrapped; read getCause() for statusCode + response body
try {
String body = helper.post(url, heads, payload, timeout);
} catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause != null && cause.getMessage() != null && cause.getMessage().contains("statusCode=")) {
log.error("manager POST rejected: {}", cause.getMessage());
} else {
log.error("manager POST failed", e);
}
throw e;
} Prevention
- 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>.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- requestPost remote error, request : {}
- requestGet remote error, url={}, code={}, error msg={}
- requestGet remote error, request : {}
- requestPost remote error, request : {}
- requestGet remote error, request : {}
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/b37aa8d053a49739.
Report an issue: GitHub.