theonedev/onedev · error · ClientException
Chart archive not found
Error message
Chart archive not found
What it means
HelmPackHandler throws this ClientException (HTTP 400) when a multipart request contains no upload item at all — items.hasNext() is false on the first iteration. The handler expects exactly one file part holding the chart .tgz; without it there is nothing to process.
Source
Thrown at server-plugin/server-plugin-pack-helm/src/main/java/io/onedev/server/plugin/pack/helm/HelmPackHandler.java:172
checkProject(projectId, true);
});
var baos = new ByteArrayOutputStream();
var contentType = request.getHeader("Content-Type");
if (contentType != null && (contentType.contains("multipart/form-data") || contentType.contains("application/x-www-form-urlencoded"))) {
try {
var upload = new ServletFileUpload();
var items = upload.getItemIterator(request);
if (items.hasNext()) {
var item = items.next();
try (var is = item.openStream()) {
var copied = IOUtils.copyWithMaxSize(is, baos, MAX_FILE_SIZE);
if (copied == -1)
throw new ClientException(SC_NOT_ACCEPTABLE, "Chart archive exceeds maximum size: " + MAX_FILE_SIZE);
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
throw new ClientException(SC_BAD_REQUEST, "Chart archive not found");
}
} catch (FileUploadException|IOException e) {
throw new RuntimeException(e);
}
} else {
try (var is = request.getInputStream()) {
var copied = IOUtils.copyWithMaxSize(is, baos, MAX_FILE_SIZE);
if (copied == -1)
throw new ClientException(SC_NOT_ACCEPTABLE, "Chart archive exceeds maximum size: " + MAX_FILE_SIZE);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Map<String, Object> metadata = null;
var bytes = baos.toByteArray();
try (var is = new TarInputStream(new GZIPInputStream(new ByteArrayInputStream(bytes)))) {
TarEntry entry;View on GitHub (pinned to d44925c47c)
Solutions
- Attach the chart archive as the first file part of the multipart request (e.g. curl -F "chart@mychart-0.1.0.tgz").
- Use helm push or the official OneDev client instead of hand-rolled requests.
- Check that the HTTP client actually reads the file (non-empty path) before sending.
- Inspect request logs/proxy to confirm the body is not stripped (Content-Length > 0).
Example fix
// before (no file attached) curl -X POST -H "Content-Type: multipart/form-data" https://onedev/~project/helm // after curl -X POST -F "chart@mychart-0.1.0.tgz" https://onedev/~project/helm
Defensive patterns
Strategy: validation
Validate before calling
# verify the file exists and is non-empty before upload
[ -s mychart-0.1.0.tgz ] || { echo 'chart archive missing'; exit 1; }
# then attach it explicitly
curl -f -X POST -F "chart@mychart-0.1.0.tgz" https://onedev/~project/helm Try / catch
try {
uploadChart(path);
} catch (ClientException e) {
if (String(e).contains('Chart archive not found')) throw new IllegalStateException("Multipart body must include the chart file part", e);
throw e;
} Prevention
- Use `helm push` or the documented client rather than hand-rolled HTTP.
- Assert file existence and non-zero size in CI before the upload step.
- Verify Content-Length > 0 at proxy level for upload endpoints.
When it happens
Trigger: POST to the helm publish endpoint with multipart content type but zero file parts, or with only non-file form fields.
Common situations: Custom scripts/CI calling the REST endpoint without attaching the chart file (wrong form field name or file omitted); HTTP client sending Content-Type: multipart/form-data with an empty body; proxy stripping the request body.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Chart archive exceeds maximum size: ${MAX_FILE_SIZE}
- Error reading chart archive: ${e.getMessage()}
- Method not allowed
- internal error
- Unauthenticated
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/5c9352e04ab8eb3c.
Report an issue: GitHub.