theonedev/onedev · error · ExplicitException

Http request failed (url: %s, status code: %d, error message

Error message

Http request failed (url: %s, status code: %d, error message: %s)

What it means

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.

Source

Thrown at server-plugin/server-plugin-import-github/src/main/java/io/onedev/server/plugin/imports/github/ImportServer.java:544

		WebTarget target = client.target(apiEndpoint);
		Invocation.Builder builder =  target.request();
		while (true) {
			try (Response response = builder.get()) {
				int status = response.getStatus();
				if (status != 200) {
					String errorMessage = response.readEntity(String.class);
					if (StringUtils.isNotBlank(errorMessage)) {
						if (errorMessage.contains("rate limit exceeded")) {
							long resetTime = Long.parseLong(response.getHeaderString("x-ratelimit-reset"))*1000L;
							logger.log("Rate limit exceeded, wait until reset...");
							try {
								Thread.sleep(resetTime + 60*1000L - System.currentTimeMillis());
								continue;
							} catch (InterruptedException e) {
								throw new RuntimeException(e);
							}
						} else {
							throw new ExplicitException(String.format("Http request failed (url: %s, status code: %d, error message: %s)", 
									apiEndpoint, status, errorMessage));
						}
					} else {
						throw new ExplicitException(String.format("Http request failed (status: %s)", status));
					}
				} 
				return response.readEntity(JsonNode.class);
			}
		}
	}

	TaskResult importProjects(ImportRepositories repositories, 
			ProjectImportOption option, boolean dryRun, TaskLogger logger) {
		Client client = newClient();
		try {
			Map<String, Optional<Long>> userIds = new HashMap<>();
			ImportResult result = new ImportResult();
			for (var gitHubRepository: repositories.getImportRepositories()) {

View on GitHub (pinned to d44925c47c)

Solutions

  1. Check the status code and error message in the exception to identify the cause
  2. Verify the access token is valid, not expired, and has the required scopes (repo for private repos)
  3. Confirm the repository name/path exists and the account can access it
  4. If rate limited, wait for the reset window (the importer already sleeps on 403 rate-limit responses); otherwise fix the request and re-run

Example fix

// before: token without repo scope -> 403/404
String token = "ghp_readonly_public_only";
// after
githubAccessToken = "ghp_..."; // token with 'repo' scope for private repositories
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify token and repo access before import:
HttpResponse<String> r = HttpClient.newHttpClient().send(
    HttpRequest.newBuilder(URI.create("https://api.github.com/repos/" + repo))
        .header("Authorization", "Bearer " + token).build(),
    HttpResponse.BodyHandlers.ofString());
if (r.statusCode() != 200) throw new IllegalStateException("GitHub API precheck failed: " + r.statusCode());

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: Expired or revoked GitHub access token (401); repository not found or private without access (404); invalid API parameters; GitHub API deprecations or secondary limits.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/3bc374958c598155. Report an issue: GitHub.