{"record":{"id":"794b3f6afa5742ad","repo":"theonedev/onedev","slug":"package-name-param-is-missing","errorCode":null,"errorMessage":"Package name param is missing","messagePattern":"Package 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":242,"sourceCode":"\t\t\t\t\t\t\tbindings.put(\"baseUrl\", \"/\" + project.getPath() + \"/~\" + HANDLER_ID + \"/files/\" + UrlUtils.encodePath(name));\n\t\t\t\t\t\t\tbindings.put(\"packs\", packs);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tURL tplUrl = Resources.getResource(getClass(), \"package-versions.tpl\");\n\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) {","sourceCodeStart":224,"sourceCodeEnd":260,"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#L224-L260","documentation":"To download a package file the URL must be /~pypi/files/<name>/<version>/<fileName>. If the package name segment is absent (fewer than 1 remaining path segment after 'files'), the handler throws ClientException(SC_BAD_REQUEST, \"Package name param is missing\") → HTTP 400.","triggerScenarios":"GET /~pypi/files with no further segments — the pathSegments.size() < 1 check at PypiPackHandler.java:241-242 fires.","commonSituations":"Hand-built download URLs missing the package name; a broken link generated by an old index template; truncated URL in a script or README example.","solutions":["Use the full three-segment path: /~pypi/files/<name>/<version>/<fileName>","Copy download links directly from the simple index page instead of hand-crafting them","Check any code that assembles file URLs for lost path segments (encoding/splitting bugs)","Ensure the trailing path isn't stripped by a proxy rewrite"],"exampleFix":"// before\nGET /myproj/~pypi/files/\n// after\nGET /myproj/~pypi/files/mypkg/1.0.0/mypkg-1.0.0-py3-none-any.whl","handlingStrategy":"validation","validationCode":"function validateFilesUrl(name, version, fileName) {\n  if (!name) throw new Error('Package name segment required: /~pypi/files/<name>/<version>/<fileName>');\n  if (!version) throw new Error('Version segment missing');\n  if (!fileName) throw new Error('File name segment missing');\n  return `~pypi/files/${encodeURIComponent(name)}/${encodeURIComponent(version)}/${encodeURIComponent(fileName)}`;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const r = await fetch(filesUrl);\n} catch (e) {\n  if (e.status === 400 && /param is missing/.test(e.message)) {\n    console.error('Malformed /files URL; need name, version and fileName segments', e);\n  } else throw e;\n}","preventionTips":["Copy download URLs from the simple index rather than building them","Url-encode each path segment (package names may contain dots/dashes)","Add link validation to scripts that scrape or generate index links"],"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"}