xpipe-io/xpipe · error · BeaconConnectorException

Couldn't parse client error message

Error message

Couldn't parse client error message

What it means

When the beacon server responds with a 4xx status, the client tries to decode the body into BeaconClientErrorResponse to surface the server-side error message. If the body cannot be parsed as that JSON shape, this BeaconConnectorException replaces the original error information.

Source

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

        if (AppProperties.get().isPrintBeaconMessages()) {
            System.out.println(
                    "Sending request to server of type " + req.getClass().getName());
        }

        return performRequest(prov.get(), node.toPrettyString());
    }

    private Optional<BeaconClientErrorResponse> parseClientError(HttpResponse<String> response)
            throws BeaconConnectorException {
        if (response.statusCode() < 400 || response.statusCode() > 499) {
            return Optional.empty();
        }

        try {
            var v = JacksonMapper.getDefault().readValue(response.body(), BeaconClientErrorResponse.class);
            return Optional.of(v);
        } catch (Exception ex) {
            throw new BeaconConnectorException("Couldn't parse client error message", ex);
        }
    }

    private Optional<BeaconServerErrorResponse> parseServerError(HttpResponse<String> response)
            throws BeaconConnectorException {
        if (response.statusCode() < 500 || response.statusCode() > 599) {
            return Optional.empty();
        }

        try {
            var v = JacksonMapper.getDefault().readValue(response.body(), BeaconServerErrorResponse.class);
            return Optional.of(v);
        } catch (Exception ex) {
            throw new BeaconConnectorException("Couldn't parse client error message", ex);
        }
    }
}

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Print response.body() (or enable printBeaconMessages) to inspect what the server actually returned on the 4xx.
  2. Ensure the client is authenticated and calling the intended beacon endpoint so real JSON error bodies are returned.
  3. Match client and daemon versions so the error response schema matches BeaconClientErrorResponse.
  4. Handle parse failure as an opaque HTTP 4xx failure instead of expecting the structured message.
Defensive patterns

Strategy: try-catch

Validate before calling

// authenticate and target the right endpoint first
boolean authed = apiKey != null && endpointPath.startsWith("/");

Try / catch

try {
    return client.performRequest(req);
} catch (BeaconConnectorException e) {
    // 4xx body was not a parseable BeaconClientErrorResponse; treat as generic HTTP failure
    LOG.warn("Beacon returned client error with unparseable body", e);
    throw new HttpRequestFailed(req, e);
}

Prevention

When it happens

Trigger: A 4xx response body is not valid JSON or does not match BeaconClientErrorResponse's fields (e.g. an HTML auth-failure page, a plain-text error from a proxy, or a schema drift between client and daemon error formats).

Common situations: API key / auth rejection returning a non-standard body; a load balancer or proxy intercepting 4xx responses; version mismatch changing the error payload layout; hitting a non-beacon HTTP endpoint by mistake.

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/4c72365a8fb541e0. Report an issue: GitHub.