{"record":{"id":"2970ddf3ee92d5c4","repo":"theonedev/onedev","slug":"specified-markdown-path-does-not-exist-or-is-a-dir","errorCode":null,"errorMessage":"Specified markdown path does not exist or is a directory (project: %s, build number: %d, path: %s)","messagePattern":"Specified markdown path does not exist or is a directory \\(project: (.+?), build number: (.+?), path: (.+?)\\)","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-report-markdown/src/main/java/io/onedev/server/plugin/report/markdown/MarkdownReportDownloadResource.java","lineNumber":84,"sourceCode":"\t\tList<String> pathSegments = new ArrayList<>();\n\t\tfor (int i = 0; i < params.getIndexedCount(); i++) {\n\t\t\tString pathSegment = params.get(i).toString();\n\t\t\tif (pathSegment.contains(\"..\"))\n\t\t\t\tthrow new ExplicitException(\"Invalid request path\");\n\t\t\tif (pathSegment.length() != 0)\n\t\t\t\tpathSegments.add(pathSegment);\n\t\t}\n\t\t\n\t\tString markdownPath = Joiner.on(\"/\").join(pathSegments);\n\t\t\n\t\tFile buildDir = build.getDir();\n\t\tFile reportDir = new File(buildDir, PublishMarkdownReportStep.CATEGORY + \"/\" + reportName);\n\t\t\n\t\tFile markdownFile = new File(reportDir, markdownPath);\n\t\tif (!markdownFile.exists() || markdownFile.isDirectory()) {\n\t\t\tString message = String.format(\"Specified markdown path does not exist or is a directory (project: %s, build number: %d, path: %s)\", \n\t\t\t\t\tproject.getPath(), build.getNumber(), markdownPath);\n\t\t\tthrow new ExplicitException(message);\n\t\t}\n\t\t\t\n\t\tResourceResponse response = new ResourceResponse();\n\t\tresponse.getHeaders().addHeader(\"X-Content-Type-Options\", \"nosniff\");\n\t\tresponse.setContentType(MimeTypes.OCTET_STREAM);\n\t\t\n\t\tresponse.disableCaching();\n\t\t\n\t\ttry {\n\t\t\tresponse.setFileName(URLEncoder.encode(markdownFile.getName(), StandardCharsets.UTF_8.name()));\n\t\t} catch (UnsupportedEncodingException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tresponse.setWriteCallback(new WriteCallback() {\n\n\t\t\t@Override\n\t\t\tpublic void writeData(Attributes attributes) throws IOException {\n\t\t\t\tLockUtils.read(PublishMarkdownReportStep.getReportLockName(build), new Callable<Void>() {","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-report-markdown/src/main/java/io/onedev/server/plugin/report/markdown/MarkdownReportDownloadResource.java#L66-L102","documentation":"After passing the traversal checks, the resource resolves the requested markdown file inside <buildDir>/markdown-reports/<reportName>/ and throws ExplicitException if the path does not exist or is a directory. The message includes the project path, build number, and the requested path so you can see exactly what was looked up. It means the build did not publish that file (or the URL points at a directory instead of a file).","triggerScenarios":"Requesting a markdown report file that was never published by the build step, a misspelled path, or a path pointing at a subdirectory instead of a .md file.","commonSituations":"Build step ran in a different build/agent and published files elsewhere; the report name or file path changed in the CI config; links to an old build whose artifacts were cleaned; requesting the report directory itself rather than an index file.","solutions":["Check the build log for the Publish Markdown Report step to confirm which files were published.","Verify the URL path matches the published file exactly (case-sensitive on Linux agents).","Re-run the build so the report is published, then retry the download.","Confirm the file exists under the build's artifact directory rather than a subdirectory."],"exampleFix":"// before\nString url = \".../markdown-reports/docs/subfolder\"; // a directory\n\n// after\nString url = \".../markdown-reports/docs/subfolder/index.md\"; // a file","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  downloadReportFile(buildId, reportName, markdownPath);\n} catch (e) {\n  if (/does not exist or is a directory/.test(e.message)) {\n    console.error('Check the Publish Markdown Report step output for build', buildId);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Verify the publish step succeeded and note the exact published paths.","Match file path casing exactly (agents are case-sensitive).","Point URLs at files, not directories.","Re-run the build if artifacts were cleaned."],"tags":["file-not-found","build-artifact","markdown-report"],"backgroundTag":"file-not-found","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"}