{"record":{"id":"763cd1ecea4b50ec","repo":"theonedev/onedev","slug":"package-file-name-param-is-missing","errorCode":null,"errorMessage":"Package file name param is missing","messagePattern":"Package file name param is missing","errorType":"http","errorClass":"ClientException","httpStatus":400,"severity":"error","filePath":"server-plugin/server-plugin-pack-pypi/src/main/java/io/onedev/server/plugin/pack/pypi/PypiPackHandler.java","lineNumber":246,"sourceCode":"\t\t\t\t\t\t\t\tString template = Resources.toString(tplUrl, UTF_8);\n\t\t\t\t\t\t\t\tresponse.setContentType(CONTENT_TYPE_SIMPLE);\n\t\t\t\t\t\t\t\tsendResponse(response, evalTemplate(template, bindings));\n\t\t\t\t\t\t\t\tresponse.setStatus(SC_OK);\n\t\t\t\t\t\t\t} catch (IOException 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\tresponse.setStatus(SC_NOT_FOUND);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (currentSegment.equals(\"files\")) {\n\t\t\t\tif (pathSegments.size() < 1)\n\t\t\t\t\tthrow new ClientException(SC_BAD_REQUEST, \"Package name param is missing\");\n\t\t\t\telse if (pathSegments.size() < 2)\n\t\t\t\t\tthrow new ClientException(SC_BAD_REQUEST, \"Package version param is missing\");\n\t\t\t\telse if (pathSegments.size() < 3)\n\t\t\t\t\tthrow new ClientException(SC_BAD_REQUEST, \"Package file name param is missing\");\n\t\t\t\t\n\t\t\t\tvar name = UrlUtils.decodePath(pathSegments.get(0));\n\t\t\t\tvar version = UrlUtils.decodePath(pathSegments.get(1));\n\t\t\t\tvar fileName = UrlUtils.decodePath(pathSegments.get(2));\n\t\t\t\t\n\t\t\t\tsessionService.run(() -> {\n\t\t\t\t\tvar project = checkProject(projectId, false);\n\t\t\t\t\tvar pack = packService.findByNameAndVersion(project, TYPE, name, version);\n\t\t\t\t\tif (pack != null) {\n\t\t\t\t\t\tvar data = (PypiData) pack.getData();\n\t\t\t\t\t\tvar sha256BlobHash = data.getSha256BlobHashes().get(fileName);\n\t\t\t\t\t\tif (sha256BlobHash != null) {\n\t\t\t\t\t\t\tPackBlob packBlob;\n\t\t\t\t\t\t\tif ((packBlob = packBlobService.checkPackBlob(projectId, sha256BlobHash)) != null) {\n\t\t\t\t\t\t\t\tresponse.setContentType(MediaType.APPLICATION_OCTET_STREAM);\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tpackBlobService.downloadBlob(packBlob.getProject().getId(),\n\t\t\t\t\t\t\t\t\t\t\tpackBlob.getSha256Hash(), response.getOutputStream());","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-pypi/src/main/java/io/onedev/server/plugin/pack/pypi/PypiPackHandler.java#L228-L264","documentation":"The /~pypi/files route requires three segments: package name, version, and file name. When the file name segment is missing (pathSegments.size() < 3 after 'files'), the handler throws ClientException(SC_BAD_REQUEST, \"Package file name param is missing\") → HTTP 400.","triggerScenarios":"GET /~pypi/files/<name>/<version> without the final file name segment (PypiPackHandler.java:245-246).","commonSituations":"Version-level listing links confused with file download links; scripts building URLs with empty file names; URL normalization stripping the last empty segment (trailing slash).","solutions":["Include the exact wheel/sdist file name as the third segment","Resolve the file name from the package-versions index page","Make sure trailing slashes are not creating/losing empty segments","Quote URLs in scripts so special characters don't break path parsing"],"exampleFix":"// before\nGET /myproj/~pypi/files/mypkg/1.0.0/\n// after\nGET /myproj/~pypi/files/mypkg/1.0.0/mypkg-1.0.0-py3-none-any.whl","handlingStrategy":"validation","validationCode":"const parts = filesUrl.split('/').filter(Boolean);\nif (parts.length < 3 || !parts[parts.length-1].match(/\\.(whl|tar\\.gz|zip|tar\\.bz2)$/)) {\n  throw new Error('File name segment missing or not a package artifact: ' + filesUrl);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const r = await fetch(filesUrl);\n  if (r.status === 400) throw new Error('Missing URL segment: ' + await r.text());\n} catch (e) { console.error(e); }","preventionTips":["Distinguish version-listing URLs from file-download URLs","Watch for trailing-slash normalization that drops the final segment","Quote URLs in shell scripts to protect special characters"],"tags":["http","url","pypi","bad-request"],"backgroundTag":"missing-required-argument","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"}