theonedev/onedev · error · ClientException

Missing version or file name

Error message

Missing version or file name

What it means

Thrown when an npm client sends a request whose path contains the '-' segment (the tarball download/publish path segment) but provides no further path segments, so OneDev cannot determine the requested version or file name. The server rejects it with HTTP 400.

Solutions

  1. Include the full tarball file name after the '-' segment: GET /npm/<project>/<scope>/<name>/-/<name>-<version>.tgz.
  2. Check the package metadata dist.tarball URL the client is using and ensure it is complete and points at the OneDev registry.
  3. If using a custom client or script, fix the URL construction to append the tarball name.

Example fix

// before
curl https://onedev.example.com/npm/proj/my-pkg/-
// after
curl -O https://onedev.example.com/npm/proj/my-pkg/-/my-pkg-1.0.0.tgz
Defensive patterns

Strategy: validation

Validate before calling

// Validate the tarball URL has a file segment after '-'
const u = new URL(pkg.dist.tarball);
const parts = u.pathname.split('/');
const dashIdx = parts.indexOf('-');
if (dashIdx === -1 || dashIdx === parts.length - 1) throw new Error('Tarball URL missing file name after - segment');

Prevention

When it happens

Trigger: Request path ending at .../<packageName>/-/ with nothing after the dash segment; the code checks pathSegments.isEmpty() immediately after matching currentSegment.equals("-").

Common situations: Misconfigured npm registry URL missing the tarball filename (e.g. dist.tarball truncated); hand-written HTTP requests or curl scripts omitting the file part of the path; broken npm client versions building malformed tarball URLs.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/df33e04af49271c1. Report an issue: GitHub.

Appendix: source

Thrown at server-plugin/server-plugin-pack-npm/src/main/java/io/onedev/server/plugin/pack/npm/NpmPackHandler.java:490

								var project = checkProject(projectId, true);
								var packs = packService.queryByName(project, TYPE, packageName, null);
								if (!packs.isEmpty()) {
									for (var pack: packs)
										packService.delete(pack);
									response.setStatus(SC_OK);									
								} else {
									response.setStatus(SC_NOT_FOUND);
								}
							});
						});
					} else if (isPut) {
						response.setStatus(SC_OK);						
					} else {
						throw new ClientException(SC_METHOD_NOT_ALLOWED);
					}
				} else if (currentSegment.equals("-")) {
					if (pathSegments.isEmpty())
						throw new ClientException(SC_BAD_REQUEST, "Missing version or file name");
					pathSegments = pathSegments.subList(1, pathSegments.size());
					if (pathSegments.size() == 1) {
						var fileName = decodePath(pathSegments.get(0));
						if (fileName.startsWith(packageName + "-")) {
							var version = substringBefore(fileName.substring(packageName.length() + 1), ".");
							sessionService.run(() -> {
								var project = checkProject(projectId, false);
								var pack = packService.findByNameAndVersion(project, TYPE, packageName, version);
								if (pack != null) {
									var packData = (NpmData) pack.getData();
									PackBlob packBlob;
									if ((packBlob = packBlobService.checkPackBlob(projectId, packData.getFileSha256BlobHash())) != null) {
										try {
											response.setContentType(MediaType.APPLICATION_OCTET_STREAM);
											packBlobService.downloadBlob(packBlob.getProject().getId(), packBlob.getSha256Hash(), response.getOutputStream());
											response.setStatus(SC_OK);
										} catch (IOException e) {
											throw new RuntimeException(e);

View on GitHub (pinned to d44925c47c)