theonedev/onedev · error · RuntimeException

internal error

Error message

internal error

What it means

During a PyPI package upload (POST multipart) handled by PypiPackHandler.handle, an IOException or FileUploadException occurred while parsing the multipart form upload. The handler wraps it in a plain RuntimeException, which OneDev surfaces to the client as a generic 'internal error'. It indicates the upload request body could not be read or parsed as multipart.

Source

Thrown at server-plugin/server-plugin-pack-pypi/src/main/java/io/onedev/server/plugin/pack/pypi/PypiPackHandler.java:188

									if (data.getSha256BlobHashes().containsKey(fileName)) {
										var errorMessage = String.format("Package already exists (name: %s, version: %s)", name, version);
										throw new ClientException(SC_CONFLICT, errorMessage);
									} 
									data.getSha256BlobHashes().put(fileName, sha256Hash);
									
									var packBlobs = data.getSha256BlobHashes().values().stream()
											.map(hash -> packBlobService.findBySha256Hash(projectId, hash))
											.filter(Objects::nonNull)
											.collect(toList());
									packService.createOrUpdate(pack, packBlobs, data.getSha256BlobHashes().size() == 1);									
								}));
								response.setStatus(SC_OK);
								break;
							}
						}
					}
				} catch (IOException | FileUploadException e) {
					throw new RuntimeException(e);
				}
			} else {
				throw new ClientException(SC_METHOD_NOT_ALLOWED);
			}
		} else {
			if (!isGet)
				throw new ClientException(SC_METHOD_NOT_ALLOWED);
			var currentSegment = pathSegments.get(0);
			pathSegments = pathSegments.subList(1, pathSegments.size());
			
			// https://peps.python.org/pep-0503/
			if (currentSegment.equals("simple")) { 
				if (pathSegments.isEmpty()) {
					sessionService.run(() -> {
						var project = checkProject(projectId, false);
						var names = packService.queryNames(project, TYPE, null, true, 0, MAX_VALUE);
						var bindings = new HashMap<String, Object>();
						bindings.put("names", names);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Check server logs for the root IOException/FileUploadException stack trace below the 'internal error' to identify the real cause
  2. Retry the twine upload and verify the multipart Content-Type and boundary are preserved end-to-end
  3. Inspect proxy/load-balancer settings for request body size limits and timeouts that could truncate the upload
  4. Verify sufficient disk space and writable temp directory on the OneDev server for multipart spooling
  5. Upgrade the client (twine) if it sends a non-standard multipart encoding
Defensive patterns

Strategy: try-catch

Validate before calling

// client side: verify multipart body before upload
const contentType = respHeaders['content-type'] || '';
if (!contentType.includes('multipart/form-data')) throw new Error('Upload must be multipart/form-data');
if (!fs.existsSync(pkgFile)) throw new Error('Package file not found: ' + pkgFile);

Try / catch

try {
  await twine.upload(repoUrl, pkgFile);
} catch (e) {
  if (e.response && /internal error/.test(e.message)) {
    console.error('Upload failed server-side; check OneDev server logs for wrapped IOException/FileUploadException', e);
  } else { throw e; }
}

Prevention

When it happens

Trigger: POSTing a package file to the ~pypi upload endpoint with a malformed multipart body, a truncated/interrupted upload, missing or malformed content-disposition part, or an invalid multipart boundary; the catch block at PypiPackHandler.java:187-188 converts the underlying IOException/FileUploadException into RuntimeException.

Common situations: twine upload interrupted by network drop; a proxy (nginx, corporate proxy) truncating or buffering the request body; client sending a non-multipart body or wrong Content-Type header; disk I/O problems on the server while spooling the upload.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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