xpipe-io/xpipe · error · BeaconConnectorException

Couldn't parse response

Error message

Couldn't parse response

What it means

After receiving a response, performRequest deserializes the JSON body into the expected response type (RES) with Jackson. If readValue fails — because the body is HTML/error text, an unexpected schema, or an empty/garbled payload — the raw exception is wrapped as BeaconConnectorException('Couldn't parse response').

Source

Thrown at app/src/main/java/io/xpipe/app/beacon/BeaconClient.java:92

            se.get().throwError();
        }

        var ce = parseClientError(response);
        if (ce.isPresent()) {
            throw ce.get().throwException();
        }

        try {
            var reader = JacksonMapper.getDefault().readerFor(prov.getResponseClass());
            var emptyResponseClass = prov.getResponseClass().getDeclaredFields().length == 0;
            var body = response.body();
            if (emptyResponseClass && body.isBlank()) {
                return createDefaultResponse(prov);
            }
            var v = (RES) reader.readValue(body);
            return v;
        } catch (Exception ex) {
            throw new BeaconConnectorException("Couldn't parse response", ex);
        }
    }

    @SneakyThrows
    @SuppressWarnings("unchecked")
    private <REQ> REQ createDefaultResponse(BeaconInterface<?> beaconInterface) {
        var c = beaconInterface.getResponseClass().getDeclaredMethod("builder");
        c.setAccessible(true);
        var b = c.invoke(null);
        var m = b.getClass().getDeclaredMethod("build");
        m.setAccessible(true);
        return (REQ) beaconInterface.getResponseClass().cast(m.invoke(b));
    }

    public <REQ, RES> RES performRequest(REQ req)
            throws BeaconConnectorException, BeaconClientException, BeaconServerException {
        ObjectNode node = JacksonMapper.getDefault().valueToTree(req);
        var prov = BeaconInterface.byRequest(req);

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Log/inspect the raw response body (enable AppProperties printBeaconMessages or print response.body()) to see what was actually returned.
  2. Align client and daemon versions so the response schema matches the compiled response classes.
  3. Confirm the request targets the correct beacon endpoint URL (no proxy interference, correct path/port).
  4. Catch BeaconConnectorException, inspect the cause (JsonProcessingException) and fall back to re-issuing the request or failing gracefully.

Example fix

// before
var res = client.performRequest(req); // may throw parse error
// after
try {
    var res = client.performRequest(req);
} catch (BeaconConnectorException e) {
    LOG.error("Beacon returned unparseable body; check daemon/client version match", e);
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// inspect body before parsing assumptions
String body = lastResponseBody; // via printBeaconMessages or response capture
boolean looksJson = body != null && body.strip().startsWith("{");

Type guard

boolean isJsonObject(String s) {
    return s != null && s.strip().startsWith("{") && s.strip().endsWith("}");
}

Try / catch

try {
    return client.performRequest(req);
} catch (BeaconConnectorException e) {
    if (e.getCause() instanceof JsonProcessingException) {
        LOG.error("Non-JSON or schema-mismatched beacon response; check client/daemon versions", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: The daemon returned non-JSON content (e.g. a proxy error page, plain-text stack trace); the response JSON does not match the expected response class fields; a version mismatch between client and daemon produces different schemas; the body is blank when a non-empty response class was expected.

Common situations: Client and xpipe daemon at different versions; an intermediary (reverse proxy, captive portal) intercepting the request; hitting the wrong endpoint/port so an HTML error page is returned; daemon bug returning malformed JSON.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06). Data as JSON: /api/errors/a1c8d443e6c1730d. Report an issue: GitHub.