{"record":{"id":"3bc374958c598155","repo":"theonedev/onedev","slug":"http-request-failed-url-s-status-code-d-err-3bc374","errorCode":null,"errorMessage":"Http request failed (url: %s, status code: %d, error message: %s)","messagePattern":"Http request failed \\(url: (.+?), status code: (.+?), error message: (.+?)\\)","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-import-github/src/main/java/io/onedev/server/plugin/imports/github/ImportServer.java","lineNumber":544,"sourceCode":"\t\tWebTarget target = client.target(apiEndpoint);\n\t\tInvocation.Builder builder =  target.request();\n\t\twhile (true) {\n\t\t\ttry (Response response = builder.get()) {\n\t\t\t\tint status = response.getStatus();\n\t\t\t\tif (status != 200) {\n\t\t\t\t\tString errorMessage = response.readEntity(String.class);\n\t\t\t\t\tif (StringUtils.isNotBlank(errorMessage)) {\n\t\t\t\t\t\tif (errorMessage.contains(\"rate limit exceeded\")) {\n\t\t\t\t\t\t\tlong resetTime = Long.parseLong(response.getHeaderString(\"x-ratelimit-reset\"))*1000L;\n\t\t\t\t\t\t\tlogger.log(\"Rate limit exceeded, wait until reset...\");\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tThread.sleep(resetTime + 60*1000L - System.currentTimeMillis());\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrow new ExplicitException(String.format(\"Http request failed (url: %s, status code: %d, error message: %s)\", \n\t\t\t\t\t\t\t\t\tapiEndpoint, status, errorMessage));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new ExplicitException(String.format(\"Http request failed (status: %s)\", status));\n\t\t\t\t\t}\n\t\t\t\t} \n\t\t\t\treturn response.readEntity(JsonNode.class);\n\t\t\t}\n\t\t}\n\t}\n\n\tTaskResult importProjects(ImportRepositories repositories, \n\t\t\tProjectImportOption option, boolean dryRun, TaskLogger logger) {\n\t\tClient client = newClient();\n\t\ttry {\n\t\t\tMap<String, Optional<Long>> userIds = new HashMap<>();\n\t\t\tImportResult result = new ImportResult();\n\t\t\tfor (var gitHubRepository: repositories.getImportRepositories()) {","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-import-github/src/main/java/io/onedev/server/plugin/imports/github/ImportServer.java#L526-L562","documentation":"The GitHub importer's get() helper performs REST API calls via Jersey. When the response has an error status that the rate-limit logic does not handle (a non-403/non-rate-limit HTTP error with a parseable error message), it throws this ExplicitException including URL, status code and the API error message.","triggerScenarios":"Any get() call (used by email(), list(), repoNode()) receiving a 401/404/422/etc. GitHub API response whose body contains an error message other than a rate-limit condition.","commonSituations":"Expired or revoked GitHub access token (401); repository not found or private without access (404); invalid API parameters; GitHub API deprecations or secondary limits.","solutions":["Check the status code and error message in the exception to identify the cause","Verify the access token is valid, not expired, and has the required scopes (repo for private repos)","Confirm the repository name/path exists and the account can access it","If rate limited, wait for the reset window (the importer already sleeps on 403 rate-limit responses); otherwise fix the request and re-run"],"exampleFix":"// before: token without repo scope -> 403/404\nString token = \"ghp_readonly_public_only\";\n// after\ngithubAccessToken = \"ghp_...\"; // token with 'repo' scope for private repositories","handlingStrategy":"try-catch","validationCode":"// Verify token and repo access before import:\nHttpResponse<String> r = HttpClient.newHttpClient().send(\n    HttpRequest.newBuilder(URI.create(\"https://api.github.com/repos/\" + repo))\n        .header(\"Authorization\", \"Bearer \" + token).build(),\n    HttpResponse.BodyHandlers.ofString());\nif (r.statusCode() != 200) throw new IllegalStateException(\"GitHub API precheck failed: \" + r.statusCode());","typeGuard":null,"tryCatchPattern":"try { node = importServer.get(client, apiEndpoint, logger); } catch (ExplicitException e) { if (e.getMessage().contains(\"status code: 40\")) { /* fix token/repo access */ } else if (e.getMessage().contains(\"403\")) { /* wait for rate-limit reset */ } else throw e; }","preventionTips":["Use a token with correct scopes and check its expiry","Confirm repository visibility/access before import","Respect rate limits; prefer smaller batches with delays"],"tags":["github","http","api","import"],"backgroundTag":"http-error-response","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}