theonedev/onedev · error · ExplicitException
Error downloading attachment (url: %s, error message: %s)
Error message
Error downloading attachment (url: %s, error message: %s)
What it means
While importing issue attachments, consume() downloads each attachment's content URL with the JAX-RS client and validates the HTTP response via JerseyUtils.checkStatus(). If the response status is not successful, checkStatus returns an error message and the import throws this ExplicitException embedding both the URL and the message, aborting the import.
Source
Thrown at server-plugin/server-plugin-import-jiracloud/src/main/java/io/onedev/server/plugin/imports/jiracloud/ImportServer.java:807
if (!dryRun) {
List<String> attachments = new ArrayList<>();
if (fieldsNode.hasNonNull("attachment")) {
long maxUploadFileSize = OneDev.getInstance(SettingService.class)
.getPerformanceSetting().getMaxUploadFileSize()*1L*1024*1024;
for (JsonNode attachmentNode: fieldsNode.get("attachment")) {
String attachmentName = attachmentNode.get("filename").asText();
int attachmentSize = attachmentNode.get("size").asInt();
if (attachmentSize > maxUploadFileSize) {
tooLargeAttachments.add(issueKey + ":" + attachmentName);
} else {
String endpoint = attachmentNode.get("content").asText();
WebTarget target = client.target(endpoint);
Invocation.Builder builder = target.request();
try (Response response = builder.get()) {
String errorMessage = JerseyUtils.checkStatus(endpoint, response);
if (errorMessage != null) {
throw new ExplicitException(String.format(
"Error downloading attachment (url: %s, error message: %s)",
endpoint, errorMessage));
}
try (InputStream is = response.readEntity(InputStream.class)) {
AttachmentService attachmentService = OneDev.getInstance(AttachmentService.class);
String oneDevAttachmentName = attachmentService.saveAttachment(
oneDevProject.getId(), issue.getUUID(), attachmentName, is);
String oneDevAttachmentUrl = oneDevProject.getAttachmentUrlPath(issue.getUUID(), oneDevAttachmentName);
attachments.add("[" + oneDevAttachmentName + "](" + oneDevAttachmentUrl + ")");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
if (!attachments.isEmpty()) {View on GitHub (pinned to d44925c47c)
Solutions
- Verify the Jira API credentials used by the import have permission to download attachments from the listed content URLs.
- Check the reported URL manually (curl) to see the actual status — if 404, the attachment is gone and must be excluded or restored in Jira.
- Ensure the Jira base URL is reachable from the OneDev server (no proxy/firewall stripping auth or blocking media CDN hosts).
- Retry the import for transient gateway/CDN errors; if a specific attachment is permanently broken, remove it in Jira and re-run.
Example fix
// before: plain unauthenticated GET to content URL fails with 403 WebTarget target = client.target(endpoint); // after: ensure client is built with the auth filter used by newClient() Client client = newClient(); // registers bearer token for media downloads WebTarget target = client.target(endpoint);
Defensive patterns
Strategy: retry
Validate before calling
try (Response r = client.target(attachmentUrl).request().get()) {
if (r.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL)
throw new IllegalStateException("Attachment not downloadable: " + r.getStatus());
} Try / catch
try { importServer.doImport(...) } catch (ExplicitException e) { if (e.getMessage().startsWith("Error downloading attachment")) { /* check URL/status in message, verify credentials, retry */ } } Prevention
- Verify token attachment-download permissions before large imports.
- Pre-check attachment content URLs for 403/404.
- Import from a network path that can reach Atlassian media/CDN hosts.
- Retry transient failures; remove permanently broken attachments in Jira.
When it happens
Trigger: consume() -> for each attachment, GET attachmentNode.get("content") returns a non-2xx response (401/403/404, expired URL, redirect to an HTML login page), so JerseyUtils.checkStatus yields a non-null errorMessage and the ExplicitException is thrown at line 807.
Common situations: Jira attachment URLs require an authenticated session/token that the plain GET does not carry; attachment deleted in Jira after issue listing (404); Jira restricts anonymous downloads; large attachments hitting a proxy/gateway error; network/CDN issues with Atlassian media URLs.
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
- Error downloading attachment (url: %s, error message: %s)
- Parameter 'attachment-group' has to be specified
- Http request failed (url: %s, status code: %d, error message
- Http request failed (status: %s)
- Import target already exists. You need to have project manag
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/1a21fee643b4427e.
Report an issue: GitHub.