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

  1. Attach the file as a multipart form part with field name exactly "file" (e.g. curl -F 'file=@mydata.bin' ...).
  2. 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.
  3. If using a custom client, verify with r.FormFile-compatible semantics: the part must be present before the handler parses the form.
  4. 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

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


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/6063dc3b71a6c3b1. Report an issue: GitHub.