vxcontrol/pentagi · error

failed to open uploaded file: %w

Error message

failed to open uploaded file: %w

What it means

SaveUploadedFileToTemp opens the multipart.FileHeader's underlying part via fh.Open(). If that fails (rare — usually a malformed multipart body or the underlying reader/pipes being broken), it returns 'failed to open uploaded file' wrapping the cause.

Source

Thrown at backend/pkg/flowfiles/files.go:320

	return true, nil
}

func RegularFileInfo(filePath string) (os.FileInfo, error) {
	info, err := os.Lstat(filePath)
	if err != nil {
		return nil, err
	}
	if !info.Mode().IsRegular() {
		return nil, fmt.Errorf("'%s' is not a regular file", filePath)
	}

	return info, nil
}

func SaveUploadedFileToTemp(fh *multipart.FileHeader, dir string) (string, error) {
	src, err := fh.Open()
	if err != nil {
		return "", fmt.Errorf("failed to open uploaded file: %w", err)
	}
	defer src.Close()

	dst, err := os.CreateTemp(dir, ".upload-*")
	if err != nil {
		return "", fmt.Errorf("failed to create temporary upload file: %w", err)
	}
	tmpPath := dst.Name()
	defer dst.Close()

	if _, err := io.Copy(dst, src); err != nil {
		os.Remove(tmpPath)
		return "", fmt.Errorf("failed to write temporary upload file: %w", err)
	}
	if err := dst.Chmod(0644); err != nil {
		os.Remove(tmpPath)
		return "", fmt.Errorf("failed to set temporary upload file permissions: %w", err)
	}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Confirm the FileHeader came from a successfully parsed request (r.ParseMultipartForm / c.FormFile), not a manually constructed struct.
  2. Check the wrapped cause (%w) for http.ErrMissingFile or reader errors and return 400 Bad Request to the client.
  3. For tests, build the FileHeader via a real multipart writer/reader round-trip instead of setting fields directly.
  4. Retry or reject on client disconnect — this is a client-side failure, not a server bug.

Example fix

// before
fh, _ := c.FormFile("file")
path, err := flowfiles.SaveUploadedFileToTemp(fh, dir) // panics/fails on nil or fake fh
// after
fh, err := c.FormFile("file")
if err != nil {
    c.JSON(400, gin.H{"error": "file part missing"}); return
}
path, err := flowfiles.SaveUploadedFileToTemp(fh, dir)
if err != nil {
    c.JSON(400, gin.H{"error": err.Error()}); return
}
Defensive patterns

Strategy: try-catch

Validate before calling

if fh == nil || fh.Size == 0 && fh.Filename == "" {
    return errors.New("no valid uploaded file part")
}

Type guard

func hasRealUpload(fh *multipart.FileHeader) bool {
    if fh == nil || fh.Filename == "" {
        return false
    }
    f, err := fh.Open()
    if err != nil {
        return false
    }
    f.Close()
    return true
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "failed to open uploaded file") {
        if errors.Is(err, http.ErrMissingFile) {
            return fmt.Errorf("client sent no file part: %w", err)
        }
        return fmt.Errorf("upload aborted or malformed: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling SaveUploadedFileToTemp with a *multipart.FileHeader whose Open() fails: a truncated or malformed multipart body, an in-memory/piped FileHeader (e.g. built manually with FileHeader{Filename: ...} without setting Content or a valid open func), or the client disconnecting mid-request so the multipart reader is closed.

Common situations: Manually constructed multipart.FileHeader values in tests or code (fh.Open() returns http.ErrMissingFile or ErrMissingBoundary-adjacent failures); aborted uploads where the client closed the connection before the form finished parsing; requests where c.File or FormFile ran against a corrupted body.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/6fa46cbff228ab10. Report an issue: GitHub.