router-for-me/CLIProxyAPI · error

no file uploaded

Error message

no file uploaded

What it means

storeUploadedAuthFile in internal/api/handlers/management/auth_files_crud.go handles multipart uploads of auth files to the management API. If the caller invokes the upload endpoint without any file part (file == nil), it rejects with `no file uploaded`. The multipart form parsing succeeded but no usable FileHeader was extracted, meaning the request was not a proper multipart file upload.

Source

Thrown at internal/api/handlers/management/auth_files_crud.go:239

		return nil, nil
	}

	keys := make([]string, 0, len(form.File))
	for key := range form.File {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	headers := make([]*multipart.FileHeader, 0)
	for _, key := range keys {
		headers = append(headers, form.File[key]...)
	}
	return headers, nil
}

func (h *Handler) storeUploadedAuthFile(ctx context.Context, file *multipart.FileHeader) (string, error) {
	if file == nil {
		return "", fmt.Errorf("no file uploaded")
	}
	name := filepath.Base(strings.TrimSpace(file.Filename))
	if !strings.HasSuffix(strings.ToLower(name), ".json") {
		return "", errAuthFileMustBeJSON
	}
	src, err := file.Open()
	if err != nil {
		return "", fmt.Errorf("failed to open uploaded file: %w", err)
	}
	defer src.Close()

	data, err := io.ReadAll(src)
	if err != nil {
		return "", fmt.Errorf("failed to read uploaded file: %w", err)
	}
	if err := h.writeAuthFile(ctx, name, data); err != nil {
		return "", err
	}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Send the request as multipart/form-data with the file under the expected field name (e.g. curl -F 'file=@auths/my.json').
  2. Verify the client HTTP library is not overriding Content-Type or stripping the form.
  3. Check the route definition for the exact form field name expected by the handler.
  4. Ensure the file part is non-empty — a named but empty part may also surface here depending on form parsing.

Example fix

# before
$ curl -X POST http://127.0.0.1:8000/v0/management/auth-files -H 'Content-Type: application/json' -d '{}'

# after
$ curl -X POST http://127.0.0.1:8000/v0/management/auth-files -F 'file=@my-codex-auth.json'
Defensive patterns

Strategy: validation

Validate before calling

// Client-side pre-check before POSTing
type uploadReq struct{ File *os.File }
func validUpload(r uploadReq) bool { return r.File != nil }

Type guard

func isNoFileUploaded(err error) bool {
    return err != nil && strings.Contains(err.Error(), "no file uploaded")
}

Prevention

When it happens

Trigger: POST to the management auth-file upload route with no `file` form part (empty body, wrong field name, or JSON body instead of multipart/form-data); sending metadata fields only; client code forgetting to attach the file.

Common situations: Automation/curl scripts that omit -F file=@...; frontend forms using the wrong input name; content-type header set to application/json by an HTTP client wrapper while the endpoint expects multipart.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/f1ab4e618faf36ea. Report an issue: GitHub.