{"record":{"id":"0a982d51cdae76ae","repo":"theonedev/onedev","slug":"error-downloading-attachment-url-s-error-messa-0a982d","errorCode":null,"errorMessage":"Error downloading attachment (url: %s, error message: %s)","messagePattern":"Error downloading attachment \\(url: (.+?), error message: (.+?)\\)","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-import-youtrack/src/main/java/io/onedev/server/plugin/imports/youtrack/ImportServer.java","lineNumber":403,"sourceCode":"\t\t\t\t\tfor (JsonNode attachmentNode : attachmentNodes) {\n\t\t\t\t\t\tString attachmentName = attachmentNode.get(\"name\").asText(null);\n\t\t\t\t\t\tString attachmentUrl = attachmentNode.get(\"url\").asText(null);\n\t\t\t\t\t\tlong attachmentSize = attachmentNode.get(\"size\").asLong(0);\n\t\t\t\t\t\tif (attachmentSize != 0 && attachmentName != null && attachmentUrl != null) {\n\t\t\t\t\t\t\tif (attachmentSize > maxUploadFileSize) {\n\t\t\t\t\t\t\t\ttooLargeAttachments.add(readableIssueId + \":\" + attachmentName);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (!attachmentUrl.startsWith(\"/api\"))\n\t\t\t\t\t\t\t\t\tthrow new ExplicitException(\"Unexpected attachment url: \" + attachmentUrl);\n\t\t\t\t\t\t\t\tattachmentUrl = attachmentUrl.substring(\"/api\".length());\n\n\t\t\t\t\t\t\t\tString endpoint = getApiEndpoint(attachmentUrl);\n\t\t\t\t\t\t\t\tWebTarget target = client.target(endpoint);\n\t\t\t\t\t\t\t\tInvocation.Builder builder = target.request();\n\t\t\t\t\t\t\t\ttry (Response response = builder.get()) {\n\t\t\t\t\t\t\t\t\tString errorMessage = JerseyUtils.checkStatus(endpoint, response);\n\t\t\t\t\t\t\t\t\tif (errorMessage != null) {\n\t\t\t\t\t\t\t\t\t\tthrow new ExplicitException(String.format(\n\t\t\t\t\t\t\t\t\t\t\t\t\"Error downloading attachment (url: %s, error message: %s)\",\n\t\t\t\t\t\t\t\t\t\t\t\tendpoint, errorMessage));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\ttry (InputStream is = response.readEntity(InputStream.class)) {\n\t\t\t\t\t\t\t\t\t\tAttachmentService attachmentService = OneDev.getInstance(AttachmentService.class);\n\t\t\t\t\t\t\t\t\t\tString oneDevAttachmentName = attachmentService.saveAttachment(\n\t\t\t\t\t\t\t\t\t\t\t\toneDevProject.getId(), issueUUID, attachmentName, is);\n\t\t\t\t\t\t\t\t\t\tString oneDevAttachmentUrl = oneDevProject.getAttachmentUrlPath(issueUUID, oneDevAttachmentName);\n\t\t\t\t\t\t\t\t\t\tif (markdown.contains(\"(\" + attachmentName + \")\")) {\n\t\t\t\t\t\t\t\t\t\t\tmarkdown = markdown.replace(\"(\" + attachmentName + \")\", \"(\" + oneDevAttachmentUrl + \")\");\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tunreferencedAttachments.put(attachmentName, oneDevAttachmentUrl);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-import-youtrack/src/main/java/io/onedev/server/plugin/imports/youtrack/ImportServer.java#L385-L421","documentation":"Thrown when downloading a YouTrack attachment: JerseyUtils.checkStatus found the HTTP response was not successful, so the importer wraps the endpoint URL and the API error message in an ExplicitException and aborts the attachment download. The attachment content is never saved to OneDev in that case.","triggerScenarios":"GET request to the constructed attachment endpoint returns a non-2xx status — expired/insufficient YouTrack token (401/403), attachment deleted in YouTrack (404), server error (5xx), or rate limiting while bulk-downloading attachments.","commonSituations":"Token permissions revoked mid-import; attachment removed from YouTrack between listing and downloading; YouTrack server overload or temporary 502 from a proxy; base URL misconfigured so the endpoint resolves wrong.","solutions":["Check the embedded error message/URL: fix the underlying HTTP cause (auth, 404, 5xx) and re-run the import.","Verify the YouTrack token is valid and has permission to read attachments.","Confirm the YouTrack base URL in connection settings is correct and reachable from the OneDev server.","Retry the import later if it was a transient 5xx/rate limit; remove re-uploaded duplicates if resuming."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-flight: verify token and attachment endpoint reachability\ntry (Response r = client.target(base + \"/api/users/me\").request().get()) {\n    if (r.getStatus() != 200) throw new IllegalStateException(\"YouTrack token invalid or insufficient\");\n}","typeGuard":null,"tryCatchPattern":"try { processAttachments(...); } catch (ExplicitException e) {\n    // message contains endpoint and API error; retry transient failures\n    logger.error(\"Attachment download failed: {}\", e.getMessage());\n}","preventionTips":["Use a long-lived token with read access to attachments.","Verify the YouTrack base URL from the OneDev server before starting.","Run imports outside peak hours to avoid 5xx/rate limiting; retry transient errors."],"tags":["youtrack","import","attachments","http","download"],"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"}