{"record":{"id":"df84aa802dcab565","repo":"xpipe-io/xpipe","slug":"authentication-failed","errorCode":null,"errorMessage":"Authentication failed","messagePattern":"Authentication failed","errorType":"exception","errorClass":"BeaconClientException","httpStatus":400,"severity":"critical","filePath":"app/src/main/java/io/xpipe/app/beacon/api/HandshakeExchange.java","lineNumber":40,"sourceCode":"    @Override\n    public boolean requiresAuthentication() {\n        return false;\n    }\n\n    @Override\n    public String getPath() {\n        return \"/handshake\";\n    }\n\n    @Override\n    public boolean requiresCompletedStartup() {\n        return false;\n    }\n\n    @Override\n    public Object handle(HttpExchange exchange, Request request) throws BeaconClientException {\n        if (!checkAuth(request.getAuth())) {\n            throw new BeaconClientException(\"Authentication failed\");\n        }\n\n        TrackEvent.withTrace(\"Handshake request received\")\n                .tag(\"client\", request.getClient().toDisplayString())\n                .handle();\n\n        var session = new BeaconSession(request.getClient(), UUID.randomUUID().toString());\n        AppBeaconServer.get().addSession(session);\n        return Response.builder().sessionToken(session.getToken()).build();\n    }\n\n    @Override\n    public boolean requiresEnabledApi() {\n        return false;\n    }\n\n    private boolean checkAuth(io.xpipe.app.beacon.BeaconAuthMethod authMethod) {\n        if (authMethod instanceof BeaconAuthMethod.Local local) {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/app/src/main/java/io/xpipe/app/beacon/api/HandshakeExchange.java#L22-L58","documentation":"The beacon handshake endpoint validates the auth value supplied by the client via checkAuth(). If the auth key/token does not match what the daemon expects, the entire handshake is rejected with a generic 'Authentication failed' message — the daemon deliberately does not reveal why. All subsequent beacon API calls require a successful handshake first.","triggerScenarios":"Calling HandshakeExchange with request.getAuth() not matching the daemon's stored beacon auth key: wrong or stale key file, daemon re-generated its key, connecting to the wrong daemon instance, or omitting/corrupting the auth value.","commonSituations":"Multiple XPipe daemon versions/instances running and the client reading the wrong auth key; daemon restart regenerating credentials while a long-lived client caches the old key; copying a client between machines; permissions preventing the client from reading the key file.","solutions":["Re-read the current beacon auth key from the daemon's key file location and retry the handshake","Confirm you are connecting to the intended daemon instance/port (not another local daemon)","Restart the client so it performs a fresh handshake instead of reusing a cached key","Check file permissions so the client process can read the key file"],"exampleFix":"// before\nhandshake(client, cachedAuthKey);\n// after\nString key = Files.readString(daemonKeyFile).trim();\nif (!Objects.equals(key, cachedAuthKey)) {\n    cachedAuthKey = key;\n}\nhandshake(client, cachedAuthKey);","handlingStrategy":"try-catch","validationCode":"String key = Files.readString(daemonKeyFile).trim();\nif (key.isEmpty()) throw new IllegalStateException(\"Beacon auth key file is empty\");","typeGuard":null,"tryCatchPattern":"try {\n    client.handshake(readCurrentKey());\n} catch (BeaconClientException e) {\n    if (e.getMessage().equals(\"Authentication failed\")) {\n        invalidateCachedKey();\n        retryHandshakeWithFreshKey();\n    } else throw e;\n}","preventionTips":["Always read the auth key fresh from the daemon's key file instead of caching","Verify daemon port/pid so you don't handshake with the wrong instance","Ensure the client process has read permission on the key file","Re-handshake after daemon restarts"],"tags":["beacon-api","authentication","handshake"],"backgroundTag":"authentication-required","analyzedSha":"d85ca821baa46092a320ebb13546d7240adb74f8","analyzedAt":"2026-09-06T14:30:08.251Z","contentChangedAt":"2026-09-06T14:30:08.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}