alibaba/canal · error · RuntimeException

requestGet remote error, url={}, code={}, error msg={}

Error message

requestGet remote error, url={}, code={}, error msg={}

What it means

Inner throw in HttpHelper.get() (HttpHelper.java:96-97): fired when the HTTP response status is not 200 OK. Builds a RuntimeException with 'requestGet remote error, url=<uri>, code=<statusCode>, error msg=<response body>'. IMPORTANT: this exception is thrown inside the try block whose catch(Throwable t) at line 99-100 immediately re-wraps it as a NEW RuntimeException ('requestGet remote error, request : <url>', originalException-as-cause). So callers never directly catch the line-96 message — it survives only as the cause of the outer exception (error 357).

Source

Thrown at instance/manager/src/main/java/com/alibaba/otter/canal/instance/manager/plain/HttpHelper.java:96

                .setConnectionRequestTimeout(timeout)
                .setSocketTimeout(timeout)
                .build();
            httpGet = new HttpGet(uri);
            if (heads != null) {
                for (Map.Entry<String, String> entry : heads.entrySet()) {
                    httpGet.setHeader(entry.getKey(), entry.getValue());
                }
            }

            HttpClientContext context = HttpClientContext.create();
            context.setRequestConfig(config);
            response = httpclient.execute(httpGet, context);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                return EntityUtils.toString(response.getEntity());
            } else {
                String errorMsg = EntityUtils.toString(response.getEntity());
                throw new RuntimeException("requestGet remote error, url=" + uri.toString() + ", code=" + statusCode
                                           + ", error msg=" + errorMsg);
            }
        } catch (Throwable t) {
            throw new RuntimeException("requestGet remote error, request : " + url, t);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    // ignore
                }
            }
            if (httpGet != null) {
                httpGet.releaseConnection();
            }
        }
    }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Read the nested cause (getCause()) of the RuntimeException thrown to the caller — it carries the original url/code/body message from line 96.
  2. Address the underlying HTTP status: 401/50014 → refresh/reissue the manager token; 404 → verify the manager base URL and REST path; 500 → inspect manager server logs; 429 → back off / raise manager rate limits.
  3. Confirm network reachability and that the manager is up: curl -i <url> with the same headers from the canal host.
  4. If using HTTPS, validate the certificate chain (the client trusts all certs via NoopHostnameVerifier, so TLS errors here are usually endpoint/protocol issues, not trust).

Example fix

// before — message lost because outer catch re-wraps
try {
    helper.get(url, heads, timeout);
} catch (RuntimeException e) {
    log.error(e.getMessage()); // only sees 'requestGet remote error, request : <url>'
}

// after — unwrap the cause to recover the status code and body
try {
    helper.get(url, heads, timeout);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause != null && cause.getMessage() != null
        && cause.getMessage().contains("code=")) {
        log.error("manager call failed: {}", cause.getMessage());
    } else {
        log.error("manager call failed", e);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: hit a cheap manager endpoint with the same headers to catch auth/404 early
try {
    int code = simpleHead(url, heads, timeout);
    if (code != 200) {
        throw new IllegalStateException("manager pre-check failed: HTTP " + code + " for " + url);
    }
} catch (IOException e) {
    throw new IllegalStateException("manager unreachable: " + url, e);
}

Try / catch

// HttpHelper re-wraps the inner throw; unwrap getCause() to recover status code + body
try {
    String body = helper.get(url, heads, timeout);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause != null && cause.getMessage() != null && cause.getMessage().contains("code=")) {
        log.error("manager GET non-200: {}", cause.getMessage());
    } else {
        log.error("manager GET failed", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: HttpHelper.get(url, heads, timeout) returns a non-200 status from the canal-manager (or whatever remote it queries). The response body is consumed as the error message, then the RuntimeException is thrown and re-wrapped by the outer catch.

Common situations: Manager auth token expired/invalid (canal-manager returns 401/50014); manager endpoint moved or load-balanced to a wrong backend returning 404; manager returns 500 due to its own DB error; rate limiting (429); SSL termination returning an error page; wrong REST path producing 404.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/177a67d5178a6461. Report an issue: GitHub.