Skip to content

chore: Improve error messages in SaveFileToStorage#4173

Open
pratikramteke wants to merge 8 commits intogofiber:mainfrom
pratikramteke:improve-error-messages
Open

chore: Improve error messages in SaveFileToStorage#4173
pratikramteke wants to merge 8 commits intogofiber:mainfrom
pratikramteke:improve-error-messages

Conversation

@pratikramteke
Copy link
Copy Markdown

Improve error messages in SaveFileToStorage by including filename and path.

This provides better debugging context when handling file upload errors.

@pratikramteke pratikramteke requested a review from a team as a code owner April 1, 2026 08:48
@ReneWerner87 ReneWerner87 added this to v3 Apr 1, 2026
@ReneWerner87 ReneWerner87 added this to the v3 milestone Apr 1, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances error reporting in the SaveFileToStorage function by including the filename and storage path in error messages. The reviewer recommends using the %q format verb instead of %s for these strings to ensure proper quoting and escaping of user-provided data, and highlights a potential information disclosure risk when including internal paths in errors.

Comment thread ctx.go Outdated
Comment thread ctx.go Outdated
Comment thread ctx.go Outdated
Comment thread ctx.go Outdated
Comment thread ctx.go Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 48627ab8-e2cd-42ea-a3d2-e7525739ca2b

📥 Commits

Reviewing files that changed from the base of the PR and between 3d08591 and 3cf3871.

📒 Files selected for processing (1)
  • ctx_test.go
✅ Files skipped from review due to trivial changes (1)
  • ctx_test.go

Walkthrough

Added explicit nil check in DefaultCtx.SaveFileToStorage and four exported sentinel file errors; SaveFileToStorage now returns/wraps these errors with filenames (and destination path for store failures). Tests added for nil fileheader and BodyLimit filename propagation. No public signatures changed.

Changes

Cohort / File(s) Summary
SaveFileToStorage implementation
ctx.go
Added early return with ErrFileHeaderNil when fileheader is nil; replaced generic errors with exported ErrFileOpen, ErrFileRead, ErrFileStore; error messages now include fileheader.Filename and destination path for store errors.
File error declarations
error.go
Added four exported error variables: ErrFileHeaderNil, ErrFileOpen, ErrFileRead, ErrFileStore.
Tests for SaveFileToStorage
ctx_test.go
Added tests verifying nil *multipart.FileHeader returns ErrFileHeaderNil and that BodyLimit/read failure error messages include the multipart filename ("test-file.png").

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • ReneWerner87
  • efectn
  • sixcolors

Poem

🐰 I hop through bytes and name each file,

I catch the nil and pause a while,
I whisper filenames when things go wrong,
I tuck the path in tidy song,
a happy rabbit, error-proof and agile.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description is minimal and lacks required sections from the template including Changes introduced checklist, Type of change selection, and Checklist items. Complete the PR description by filling out the template sections: select a Type of change (e.g., Enhancement, Code consistency), check relevant Checklist items, and describe any documentation or test updates.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: improving error messages in SaveFileToStorage with better context (filename and path).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.4)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

pratikramteke and others added 3 commits April 1, 2026 14:26
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Comment thread ctx.go Outdated
file, err := fileheader.Open()
if err != nil {
return fmt.Errorf("failed to open: %w", err)
return fmt.Errorf("failed to open file %s: %w", fileheader.Filename, err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the fileader is nil, it is going to panic. you also need to add check for that. In addition to panic check, could you also unit test cases for error messages?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't err have the filename already?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no it only shows what the error is https://pkg.go.dev/internal/oserror#pkg-variables

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 1, 2026

Codecov Report

❌ Patch coverage is 57.14286% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.22%. Comparing base (bf952a1) to head (3364650).

Files with missing lines Patch % Lines
ctx.go 57.14% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4173   +/-   ##
=======================================
  Coverage   91.22%   91.22%           
=======================================
  Files         123      123           
  Lines       11832    11834    +2     
=======================================
+ Hits        10794    10796    +2     
  Misses        653      653           
  Partials      385      385           
Flag Coverage Δ
unittests 91.22% <57.14%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ReneWerner87
Copy link
Copy Markdown
Member

@pratikramteke pls check the hints

@gaby gaby changed the title improve error messages in SaveFileToStorage chore: Improve error messages in SaveFileToStorage Apr 2, 2026
@gaby
Copy link
Copy Markdown
Member

gaby commented Apr 2, 2026

@pratikramteke The error needs to be defined in error.go. Then returned that predefined error.

@efectn
Copy link
Copy Markdown
Member

efectn commented Apr 3, 2026

Please check unit tests and lintci errors

Comment thread ctx.go
file, err := fileheader.Open()
if err != nil {
return fmt.Errorf("failed to open: %w", err)
return fmt.Errorf("%w: %q: %v", ErrFileOpen, fileheader.Filename, err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we better sanitize filename for security reasons

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filename comes from the Client Request, so they already know it.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to improve debugging for SaveFileToStorage failures by adding file-related sentinel errors and including more context (e.g., filename/path) in returned errors.

Changes:

  • Added new exported file-related sentinel errors in error.go.
  • Updated DefaultCtx.SaveFileToStorage to return those sentinel errors and to include filename/path details in error messages.
  • Added tests covering nil file header handling and verifying that error messages include the filename.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
error.go Adds exported sentinel errors for file operations used by SaveFileToStorage.
ctx.go Updates SaveFileToStorage to use new sentinel errors and enrich error messages.
ctx_test.go Adds tests for nil file headers and filename presence in error messages.

Comment thread ctx.go
limitedReader := io.LimitReader(file, int64(maxUploadSize)+1)
if _, err = buf.ReadFrom(limitedReader); err != nil {
return fmt.Errorf("failed to read: %w", err)
return fmt.Errorf("%w: %q: %v", ErrFileRead, fileheader.Filename, err)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buf.ReadFrom errors are formatted with %v, so they are not wrapped and can’t be matched with errors.Is/As. Wrap the underlying read error with %w (while still wrapping ErrFileRead).

Suggested change
return fmt.Errorf("%w: %q: %v", ErrFileRead, fileheader.Filename, err)
return fmt.Errorf("%w: %q: %w", ErrFileRead, fileheader.Filename, err)

Copilot uses AI. Check for mistakes.
Comment thread ctx.go
Comment on lines 547 to 549
if buf.Len() > maxUploadSize {
return fmt.Errorf("failed to read: %w", fasthttp.ErrBodyTooLarge)
return fmt.Errorf("%w: %q: %v", ErrFileRead, fileheader.Filename, fasthttp.ErrBodyTooLarge)
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When buf.Len() > maxUploadSize, fasthttp.ErrBodyTooLarge is again included with %v instead of being wrapped. This prevents errors.Is(err, fasthttp.ErrBodyTooLarge) from working. Wrap it with %w (and keep wrapping ErrFileRead).

Copilot uses AI. Check for mistakes.
Comment thread ctx.go

if err := storage.SetWithContext(c.Context(), path, data, 0); err != nil {
return fmt.Errorf("failed to store: %w", err)
return fmt.Errorf("%w: %q to %q: %v", ErrFileStore, fileheader.Filename, path, err)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The storage SetWithContext error is formatted with %v, so the underlying storage error is not wrapped. Wrap the original error with %w so callers can errors.Is/As on the storage-specific error type (while still wrapping ErrFileStore).

Suggested change
return fmt.Errorf("%w: %q to %q: %v", ErrFileStore, fileheader.Filename, path, err)
return fmt.Errorf("%w: %q to %q: %w", ErrFileStore, fileheader.Filename, path, err)

Copilot uses AI. Check for mistakes.
Comment thread ctx.go
Comment on lines 524 to 537
@@ -529,25 +533,25 @@ func (c *DefaultCtx) SaveFileToStorage(fileheader *multipart.FileHeader, path st
}

if fileheader.Size > 0 && fileheader.Size > int64(maxUploadSize) {
return fmt.Errorf("failed to read: %w", fasthttp.ErrBodyTooLarge)
return fmt.Errorf("%w: %q: %v", ErrFileRead, fileheader.Filename, fasthttp.ErrBodyTooLarge)
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says errors should include both filename and path, but the open/read error paths only include fileheader.Filename (the path argument isn’t mentioned until the store failure case). Either include path in these earlier error messages too, or adjust the PR description/tests to match the intended behavior.

Copilot uses AI. Check for mistakes.
Comment thread ctx_test.go
err := ctx.SaveFileToStorage(fileHeader, "test-path", storage)

require.Error(t, err)
require.Contains(t, err.Error(), "test-file.png")
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test asserts that the error message contains the filename, but it doesn’t validate the "path" part mentioned in the PR description. If the intent is to include both filename and destination path for debugging context, add an assertion for the path as well (and update the implementation accordingly so the failing code path includes it).

Suggested change
require.Contains(t, err.Error(), "test-file.png")
require.Contains(t, err.Error(), "test-file.png")
require.Contains(t, err.Error(), "test-path")

Copilot uses AI. Check for mistakes.
Comment thread ctx.go
Comment on lines 524 to 527
file, err := fileheader.Open()
if err != nil {
return fmt.Errorf("failed to open: %w", err)
return fmt.Errorf("%w: %q: %v", ErrFileOpen, fileheader.Filename, err)
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underlying err from fileheader.Open() is formatted with %v, so it is not wrapped. This breaks errors.Is/As for callers and makes it harder to detect the root cause programmatically. Wrap the underlying error (use %w) while still including the filename in the message (Go supports multiple %w).

Copilot uses AI. Check for mistakes.
Comment thread ctx.go
Comment on lines 535 to 537
if fileheader.Size > 0 && fileheader.Size > int64(maxUploadSize) {
return fmt.Errorf("failed to read: %w", fasthttp.ErrBodyTooLarge)
return fmt.Errorf("%w: %q: %v", ErrFileRead, fileheader.Filename, fasthttp.ErrBodyTooLarge)
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fasthttp.ErrBodyTooLarge is included using %v, so the returned error no longer wraps it. Existing callers/tests that rely on errors.Is(err, fasthttp.ErrBodyTooLarge) will fail. Use %w for fasthttp.ErrBodyTooLarge (and keep wrapping ErrFileRead).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

5 participants