argoproj/argo-workflows · error
Failed to get file from form:
Error message
Failed to get file from form:
What it means
The artifact upload HTTP endpoint requires a multipart/form-data body containing a file part named exactly "file". This error is returned by UploadInputArtifact when r.FormFile("file") fails — the part is missing or named differently. It is a client-side request-shape problem, always returned with HTTP 400.
Source
Thrown at server/artifacts/artifact_server.go:174
defer func() {
if r.MultipartForm != nil {
_ = r.MultipartForm.RemoveAll()
}
}()
// Parse multipart form (max 32MB in memory, rest on disk)
if parseErr := r.ParseMultipartForm(32 << 20); parseErr != nil {
if _, ok := errors.AsType[*http.MaxBytesError](parseErr); ok {
http.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)
return
}
http.Error(w, "Failed to parse multipart form: "+parseErr.Error(), http.StatusBadRequest)
return
}
file, header, err := r.FormFile("file")
if err != nil {
http.Error(w, "Failed to get file from form: "+err.Error(), http.StatusBadRequest)
return
}
defer file.Close()
a.logger.WithFields(logging.Fields{
"filename": header.Filename,
"size": header.Size,
}).Info(ctx, "Received file for upload")
// Find the artifact in the WorkflowTemplate's arguments.artifacts
var templateArtifact *wfv1.Artifact
if wfTemplate.Spec.Arguments.Artifacts != nil {
for i := range wfTemplate.Spec.Arguments.Artifacts {
if wfTemplate.Spec.Arguments.Artifacts[i].Name == artifactName {
templateArtifact = &wfTemplate.Spec.Arguments.Artifacts[i]
break
}
}View on GitHub (pinned to 35bff19146)
Solutions
- Attach the file as a multipart form part with field name exactly "file" (e.g. curl -F 'file=@mydata.bin' ...).
- Ensure the Content-Type of the request is multipart/form-data with a proper boundary — do not set it manually; let the HTTP client generate it.
- If using a custom client, verify with r.FormFile-compatible semantics: the part must be present before the handler parses the form.
- Check any intermediary proxy/gateway preserves the multipart body unchanged.
Example fix
// before (wrong field name) curl -X POST -F 'upload=@data.bin' $SERVER/api/v1/workflows/$NS/$WF/input-artifacts/$NAME // after curl -X POST -F 'file=@data.bin' $SERVER/api/v1/workflows/$NS/$WF/input-artifacts/$NAME
Defensive patterns
Strategy: validation
Validate before calling
const fd = new FormData();
if (!file) throw new Error('upload aborted: no file selected');
fd.append('file', file, file.name); // field name MUST be 'file'
// sanity check before send:
if (![...fd.keys()].includes('file')) throw new Error('form missing "file" part'); Try / catch
try {
const res = await fetch(url, { method: 'POST', body: fd }); // let client set multipart Content-Type
if (res.status === 400) throw new Error('Server rejected form: ' + await res.text());
} catch (e) { /* fix field name / Content-Type and retry once */ } Prevention
- Always use the field name 'file' when appending to FormData.
- Never set the multipart Content-Type header manually; let the client generate the boundary.
- Smoke-test uploads with curl -F 'file=@...' before wiring custom clients.
- Log the request body shape client-side when developing new upload integrations.
When it happens
Trigger: POSTing to the input-artifact upload endpoint with no part named "file"; using a different field name (e.g. "artifact", "upload", "data"); sending JSON or raw bytes instead of multipart/form-data; a client library that streams multipart incorrectly so the part never materializes after ParseMultipartForm.
Common situations: Hand-rolled curl/Python/JS clients that use the wrong form field name; users crafting a raw POST in Postman/Insomnia without a file field; SDK version mismatches where the client changed the field name; proxies or gateways that strip or re-encode multipart bodies.
Related errors
- Failed to parse multipart form:
- failed to stream artifact: %v
- CodeNotFound
- CodeNotImplemented
- CodeBadRequest
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/6063dc3b71a6c3b1.
Report an issue: GitHub.