{"record":{"id":"1d96e51f06f9ce64","repo":"xpipe-io/xpipe","slug":"received-http-statuscode-without-further-detail","errorCode":null,"errorMessage":"Received HTTP ${statusCode} without further details","messagePattern":"Received HTTP (.+?) without further details","errorType":"http","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/xpipe/app/util/HttpHelper.java","lineNumber":121,"sourceCode":"\n                        @Override\n                        public String getDescription() {\n                            return AppI18n.get(\"httpProxyErrorDescription\");\n                        }\n\n                        @Override\n                        public boolean handle(ErrorEvent event) {\n                            AppPrefs.get().selectCategory(\"httpProxy\");\n                            return true;\n                        }\n                    }));\n            throw ex;\n        }\n\n        if (res.statusCode() >= 400) {\n            if (res.body() instanceof String s) {\n                var msg = !s.isEmpty() ? s : \"Received HTTP \" + res.statusCode() + \" without further details\";\n                throw new IOException(msg);\n            } else if (res.body() instanceof byte[] b) {\n                var msg = b.length > 0\n                        ? new String(b, StandardCharsets.UTF_8)\n                        : \"Received HTTP \" + res.statusCode() + \" without further details\";\n                throw new IOException(msg);\n            }\n        }\n    }\n}\n","sourceCodeStart":103,"sourceCodeEnd":131,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/app/src/main/java/io/xpipe/app/util/HttpHelper.java#L103-L131","documentation":"HttpHelper.checkOrThrow converts any HTTP response with status >= 400 into an IOException. When the response body is a String and empty (or no body text is available), it throws this generic message including only the status code. It exists so failed HTTP calls never pass silently.","triggerScenarios":"Calling an HttpHelper request whose response status is >= 400 (404, 401, 500, etc.) with a String body that is empty, so no server-provided error detail exists.","commonSituations":"Hitting an endpoint that returns bare status codes without error bodies (e.g. load balancer 502/503, HEAD-like responses); wrong URL returning empty 404; expired auth returning empty 401.","solutions":["Log/check res.statusCode() to identify the failure class","Verify the request URL, method, and headers are correct","Add authentication or refresh credentials if the status is 401/403","Retry with backoff for transient 5xx statuses; inspect server logs for 5xx"],"exampleFix":"// before: ignoring status\nvar res = HttpHelper.send(request);\n// after: handle error statuses explicitly\nvar res = HttpHelper.send(request);\ntry {\n    HttpHelper.checkOrThrow(res);\n} catch (IOException e) {\n    throw new IOException(\"request to \" + res.uri() + \" failed: \" + e.getMessage(), e);\n}","handlingStrategy":"validation","validationCode":"if (res.statusCode() >= 400) {\n    throw new IOException(\"HTTP \" + res.statusCode() + \" from \" + res.uri() + \" before processing\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    HttpHelper.checkOrThrow(res);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"Received HTTP 4\")) {\n        // fix request/auth\n    } else {\n        // retry/backoff for 5xx\n    }\n}","preventionTips":["Always call checkOrThrow right after receiving a response","Log status code and URI with every HTTP failure","Handle 401/403 with credential refresh flows","Use backoff for transient 5xx"],"tags":["http","network"],"backgroundTag":"http-error-response","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"}