gofiber/fiber · error · ErrFileOpen
%w: %q: %w
Error message
%w: %q: %w
What it means
Returned by Ctx.SaveFileToStorage when multipart.FileHeader.Open() fails while accessing the uploaded file's content. The error wraps the sentinel ErrFileOpen ('file: failed to open file'), the original filename, and the underlying OS/multipart error: 'file: failed to open file: "report.pdf": <err>'. This is an early failure in the save-to-storage pipeline, before size limiting or reading begins.
Source
Thrown at ctx.go:572
}
// SaveFile saves any multipart file to disk.
func (*DefaultCtx) SaveFile(fileheader *multipart.FileHeader, path string) error {
if fileheader == nil {
return ErrFileHeaderNil
}
return fasthttp.SaveMultipartFile(fileheader, path)
}
// SaveFileToStorage saves any multipart file to an external storage system.
func (c *DefaultCtx) SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error {
if fileheader == nil {
return ErrFileHeaderNil
}
file, err := fileheader.Open()
if err != nil {
return fmt.Errorf("%w: %q: %w", ErrFileOpen, fileheader.Filename, err)
}
defer file.Close() //nolint:errcheck // not needed
maxUploadSize := c.app.config.BodyLimit
if maxUploadSize <= 0 {
maxUploadSize = DefaultBodyLimit
}
if fileheader.Size > 0 && fileheader.Size > int64(maxUploadSize) {
return fmt.Errorf("%w: %q: %w", ErrFileRead, fileheader.Filename, fasthttp.ErrBodyTooLarge)
}
buf := bytebufferpool.Get()
defer bytebufferpool.Put(buf)
limitedReader := io.LimitReader(file, int64(maxUploadSize)+1)
if _, err = buf.ReadFrom(limitedReader); err != nil {
return fmt.Errorf("%w: %q: %w", ErrFileRead, fileheader.Filename, err)View on GitHub (pinned to a105acad6c)
Solutions
- Do not read or save the same multipart file twice; consume it once in a single handler.
- Inspect the wrapped underlying error (errors.Unwrap / errors.Is(err, ErrFileOpen)) to identify the OS cause.
- If reproducing in tests, build the FileHeader from real multipart data via a httptest request rather than a hand-constructed struct.
- Handle the error with a 4xx/5xx response appropriate to the cause (client gone vs. server I/O).
Example fix
if err := c.SaveFileToStorage(fh, key, store); err != nil {
if errors.Is(err, fiber.ErrFileOpen) {
return c.Status(fiber.StatusBadGateway).SendString("could not open upload")
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
if err := c.SaveFileToStorage(fh, key, store); err != nil {
if errors.Is(err, fiber.ErrFileOpen) {
// underlying multipart part could not be opened
return fiber.NewError(fiber.StatusBadRequest, "upload unavailable")
}
return err
} Prevention
- Consume each multipart file exactly once in a single handler.
- Do not hand-construct multipart.FileHeader in tests; use a real httptest multipart request.
- Branch on errors.Is(err, fiber.ErrFileOpen) to separate open failures from read/store failures.
- Log the unwrapped underlying error to pinpoint OS causes.
When it happens
Trigger: Calling c.SaveFileToStorage(fileheader, path, storage) where the multipart header is present but its underlying part cannot be opened. The fileheader must be non-nil (a nil header returns ErrFileHeaderNil earlier).
Common situations: The upload was already consumed/drained by an earlier handler, the temp file backing the multipart part was deleted under the process, or the OS returned an I/O error opening the spilled part. Rare in normal operation; more likely in tests that hand-craft FileHeader values.
Related errors
- file: failed to open file
- %w: %q to %q: %w
- the file should have a name
- file: file header is nil
- boundary generation: %w
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/724a831aaa6bc096.
Report an issue: GitHub.