Skip to content

Conversation

@forest6511
Copy link
Owner

@forest6511 forest6511 commented Nov 9, 2025

Summary

Standardized error handling across the entire codebase using a unified structured pattern. This significantly improves error diagnostics, maintainability, and consistency.

Changes

Phase 2: Error Handling Infrastructure Enhancement (Commit 3970c6f)

Added 9 new helper functions to establish a unified error handling pattern:

  • NewDownloadError(code, message) - Simple error generation
  • WrapError(underlying, code, message) - Generic error wrapping
  • WrapErrorWithURL(underlying, code, message, url) - Wrapping with URL context
  • NewValidationError(field, reason) - Field validation errors
  • NewStorageError(operation, underlying, details) - Storage operation errors
  • NewConfigError(message, underlying, details) - Configuration errors
  • NewPluginError(name, underlying, details) - Plugin errors
  • NewInvalidPathError(path, underlying) - Path errors
  • FromHTTPStatus(statusCode, url) - Error generation from HTTP status

Phase 3: Migration of All 353 Errors (8 Commits)

Systematically migrated from fmt.Errorf/errors.New to structured errors:

Commit Target Scope Migration Count
0c94848 pkg/ packages 109
eb8ad51 internal/core 17
c167ad7 internal/protocols 30
4311794 Storage Layer 43
0af3637 Internal Utilities 68
d35cae3 Core Library 60
66b373e Application Layer 25
ef35f88 Final Fix 1

Total: 353 errors migrated

Intentionally Excluded Elements

The following were intentionally excluded due to standard Go patterns or technical constraints:

  • pkg/storage/errors.go:7-12 - Sentinel errors (equivalent to io.EOF)
  • pkg/middleware/middleware.go:480 - Error restoration from cache
  • All test files (*_test.go)
  • All example code (examples/*)

Benefits

1. Enhanced Diagnostics

  • Structured error codes (CodeNetworkError, CodeStorageError, etc.)
  • Rich context information (URL, file path, details)
  • Error chain preservation (Underlying field)

2. Improved Maintainability

  • Unified error handling pattern
  • Consistent error message formatting
  • Reusable helper functions

3. Better Programmability

  • Full compatibility with errors.Is()/errors.As()
  • Type-safe access to structured error fields
  • Automatic retryability determination

Testing

  • ✅ All 43 packages pass tests
  • ✅ All existing error handling tests succeed
  • ✅ Zero regressions

Backward Compatibility

  • ✅ No breaking changes to public API (exported)
  • ✅ Full compatibility with error interface
  • ✅ Existing error checking code works as-is

Related Issue

Closes #39

Reviewer Checklist

  • Are error code selections appropriate?
  • Are error messages clear and helpful for diagnostics?
  • Is context information (URL, paths, etc.) properly preserved?
  • Do all tests pass?
  • Is documentation sufficient?

- Add 5 new error codes (CodeInvalidPath, CodePluginError, CodeConfigError, CodeValidationError, CodeStorageError)
- Add 5 lightweight helper functions (NewInvalidPathError, NewPluginError, NewConfigError, NewValidationError, NewStorageError)
- Create pkg/errors/formatter.go with 6 UI/CLI helper functions
- Fix AsDownloadError to use standard library errors.As
- Improve Retryable judgment in helper functions based on underlying error

All changes reviewed and approved by CODEX. All tests passing.
Migrate 109 errors from fmt.Errorf/errors.New to structured DownloadError
pattern across pkg/ packages, with CODEX review fixes and test updates.

## Migration Summary (109 errors → DownloadError)
- pkg/config: 10 errors (config.go)
- pkg/ui: 2 errors (formatter.go)
- pkg/middleware: 9 errors (middleware.go)
- pkg/cli: 26 errors (plugin.go)
- pkg/plugin: 62 errors (config_migration.go, hotreload.go, loader.go,
  manager.go, security.go, version.go)

## CODEX Review Fixes (5 critical issues)
Fixed error code misclassification and context loss:
1. pkg/cli/plugin.go L231: Preserve GetEnabledPlugins error
2. pkg/middleware/middleware.go L148: Preserve context errors in rate limiter
3. pkg/middleware/middleware.go L380: Preserve original error codes in retry
4. pkg/plugin/hotreload.go L277: Preserve loadPlugin error
5. pkg/plugin/manager.go L231: Return first error instead of wrapping
6. pkg/plugin/version.go L158: Preserve ParseVersion metadata

## Test Updates (28 tests across 4 files)
Updated test expectations to match structured error formats:
- pkg/cli/plugin_test.go: 11 tests
- pkg/cli/plugin_coverage_test.go: 3 tests
- pkg/plugin/loader_test.go: 6 tests
- pkg/plugin/plugin_test.go: 1 test

## Validation
- ✅ All 402 tests pass (go test ./pkg/...)
- ✅ Error code preservation verified
- ✅ CODEX review validated migration approach
- ✅ Pre-commit hooks passed

## Related
- Issue #39: Error Handling Standardization
- Phase 3 Progress: 109/320 errors (34% complete)
- Next: internal/core migration (17 errors)
Migrate 17 errors from fmt.Errorf to structured DownloadError pattern
in internal/core package (downloader.go, lightweight.go, zerocopy.go).

## Migration Details (17 errors → DownloadError)
- internal/core/downloader.go: 1 error (HTTP status checking)
  * L1548: Use FromHTTPStatus for resume response validation
- internal/core/lightweight.go: 8 errors (HTTP operations)
  * L43, L79: WrapErrorWithURL for request creation (CodeInvalidURL)
  * L52, L88: WrapErrorWithURL for request execution (CodeNetworkError)
  * L57, L93: FromHTTPStatus for status code errors
  * L64, L112: WrapErrorWithURL for write failures (CodeNetworkError)
- internal/core/zerocopy.go: 8 errors (zero-copy operations)
  * L34, L97: WrapErrorWithURL for request creation (CodeInvalidURL)
  * L39, L102: WrapErrorWithURL for request execution (CodeNetworkError)
  * L44, L107: FromHTTPStatus for status code errors
  * L51, L114: NewStorageError for file creation failures

## Helper Functions Used
- WrapErrorWithURL: Network errors with URL context
- FromHTTPStatus: HTTP status code to appropriate error code mapping
- NewStorageError: File system operation errors

## Validation
- ✅ All 191 tests pass (go test ./internal/core/... -v)
- ✅ Build successful (go build ./internal/core/...)
- ✅ Removed unused fmt imports after migration

## Related
- Issue #39: Error Handling Standardization
- Phase 3 Progress: 126/320 errors (39% complete)
- Next: internal/protocols migration (30 errors)
Migrate 30 errors from fmt.Errorf to structured DownloadError pattern
in internal/protocols package (FTP and S3 handlers).

## Migration Details (30 errors → DownloadError)

### internal/protocols/ftp/handler.go (15 errors)
- L106, L161, L215, L242: WrapError for URL parsing (CodeInvalidURL)
- L131: WrapError for connection failures (CodeNetworkError)
- L141: WrapError for authentication failures (CodeAuthenticationFailed)
- L167, L220: NewValidationError for missing file paths
- L177, L189, L226, L253: WrapError for FTP operations (CodeNetworkError)
- L201: WrapError for context cancellation (CodeCancelled)
- L284, L293: NewDownloadError for disconnected client state

### internal/protocols/s3/handler.go (15 errors)
- L61, L105: WrapError for AWS config (CodeConfigError)
- L125: WrapError for URL parsing (CodeInvalidURL)
- L129, L136, L140: NewValidationError for URL components
- L161, L172, L193, L219, L249, L269, L315, L325: WrapError for S3 operations (CodeNetworkError)
- L197: NewDownloadError for missing content length (CodeServerError)

### Test Updates
- internal/protocols/s3/handler_test.go: Updated error checking to use errors.Is() for proper error unwrapping

## Helper Functions Used
- WrapError: Wrap underlying errors with appropriate error codes
- NewDownloadError: Create simple errors without underlying error
- NewValidationError: Field validation errors

## Validation
- ✅ Build successful (go build ./internal/protocols/...)
- ✅ All tests pass (FTP: 93.7s, S3: 1.0s)
- ✅ Context information preserved (servers, paths, buckets, ranges)

## Related
- Issue #39: Error Handling Standardization
- Phase 3 Progress: 156/320 errors (49% complete)
- Next: Other utilities migration (164 errors)
Migrate 43 error instances in storage layer to use DownloadError pattern:
- pkg/storage/backends/s3.go (11 errors)
- pkg/storage/backends/redis.go (15 errors)
- pkg/storage/backends/filesystem.go (14 errors)
- internal/storage/checker.go (2 errors)
- internal/storage/checker_windows.go (1 error)

Error codes applied:
- CodeStorageError: File I/O, database, and cache operations (30)
- CodeInvalidPath: Path validation and security (2)
- CodeValidationError: Configuration validation (2)
- CodeNetworkError: Redis connection failures (1)
- CodeAuthenticationFailed: AWS credential errors (1)
- CodeCancelled: Context cancellation (1)
- CodeConfigError: Client initialization (1)

All tests passing: pkg/storage, pkg/storage/backends, internal/storage

Progress: 199/320 errors migrated (62%)
Next: Internal utilities migration (53 errors)
Migrate 68 error instances in internal utilities to DownloadError pattern:
- internal/concurrent/manager.go (22 errors)
- internal/concurrent/worker.go (17 errors)
- internal/resume/resume.go (15 errors)
- internal/retry/manager.go (10 errors)
- internal/network/diagnostics.go (2 errors)

Error codes applied:
- CodeNetworkError: Network operations (26)
- CodeStorageError: File/directory operations (14)
- CodeTimeout: Rate limiting, retry exhaustion (8)
- CodeCancelled: Context cancellation (4)
- CodeValidationError: Data validation (4)
- CodeInvalidPath: Path validation (1)
- CodeCorruptedData: Size mismatch (1)

Key improvements:
- URLs attached via WrapErrorWithURL()
- File paths attached via NewStorageError()
- Worker IDs and chunk indices preserved
- No re-wrapping via GetErrorCode() checks
- Removed unused fmt import from retry/manager.go

Test results: All passing with maintained coverage
- internal/concurrent: 90.4% coverage
- internal/resume: 89.0% coverage
- internal/retry: 86.1% coverage
- internal/network: 86.8% coverage

Progress: 267/320 errors migrated (83%)
Next: Core library migration (58 errors)
Migrate 60 error instances in core library to DownloadError pattern:
- gdl.go (15 errors) - Main API functions
- pkg/validation/validation.go (24 errors) - Input validation
- pkg/protocols/registry.go (16 errors) - Protocol handlers
- pkg/ratelimit/parser.go (5 errors) - Rate limit parsing

Error codes applied:
- CodeInvalidURL: URL parsing/validation (12)
- CodeValidationError: Input validation (32 via NewValidationError)
- CodeInvalidPath: File path validation (5)
- CodePermissionDenied: Directory access (2)
- CodeNetworkError: Protocol handlers (2)
- CodeStorageError: File operations (2)
- CodePluginError: Plugin hooks (1)
- CodeConfigError: Configuration (1)

Key improvements:
- All validation errors use NewValidationError(field, reason)
- URL errors preserve context via WrapErrorWithURL()
- Path security via NewInvalidPathError()
- No behavior changes - all existing tests pass

Test results: All core library tests passing
- pkg/validation: 9 test cases
- pkg/protocols: 14 test cases
- pkg/ratelimit: All tests passing
- gdl.go: Top-level API tests passing

Progress: 327/320 errors migrated (102%)
Next: Application layer migration (final phase)
Migrate final 25 error instances to complete error standardization:
- cmd/gdl/main.go (19 errors) - CLI application
- pkg/hooks/executor.go (3 errors) - Plugin hooks
- pkg/cli/plugin.go (2 errors) - Plugin CLI stubs
- pkg/monitoring/metrics.go (1 error) - Metrics tracking

Error codes applied:
- CodeValidationError: Input validation, parameters (11)
- CodePluginError: Plugin operations (4)
- CodeCancelled: User cancellations (3)
- CodeUnknown: Unimplemented features (2)
- CodeConfigError: Configuration setup (1)
- CodeNetworkError: Network conditions (1)
- CodeInsufficientSpace: Disk space (1)
- CodeInvalidURL: URL parsing (1)

Key improvements:
- CLI error messages remain user-friendly and actionable
- All plugin errors wrapped via NewPluginError()
- "Not implemented" stubs converted to CodeUnknown
- All error context preserved (paths, names, URLs)

Test results: 100% pass rate across all application tests
- cmd/gdl: PASS (0.986s)
- pkg/hooks: PASS (0.201s)
- pkg/cli: PASS (0.821s)
- pkg/monitoring: PASS (0.469s)

Phase 3 Migration Complete: 352/320 errors migrated (110%)
Next: Phase 4 - Comprehensive validation and testing
- Use gdlerrors.FromHTTPStatus instead of fmt.Errorf for HTTP status errors
- Ensures consistent error handling throughout concurrent download manager
- Final fix for Issue #39 error standardization

Related: #39
@codecov
Copy link

codecov bot commented Nov 9, 2025

Codecov Report

❌ Patch coverage is 69.65812% with 213 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.51%. Comparing base (d0b52d0) to head (f75a173).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/config/config.go 73.98% 32 Missing ⚠️
pkg/storage/backends/redis.go 9.52% 19 Missing ⚠️
internal/concurrent/manager.go 54.28% 16 Missing ⚠️
gdl.go 6.66% 14 Missing ⚠️
pkg/cli/plugin.go 61.76% 13 Missing ⚠️
pkg/storage/backends/filesystem.go 33.33% 12 Missing ⚠️
pkg/storage/backends/s3.go 42.85% 12 Missing ⚠️
cmd/gdl/main.go 42.10% 11 Missing ⚠️
internal/core/lightweight.go 21.42% 11 Missing ⚠️
pkg/plugin/loader.go 61.53% 10 Missing ⚠️
... and 14 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #49      +/-   ##
==========================================
+ Coverage   84.41%   84.51%   +0.09%     
==========================================
  Files          61       62       +1     
  Lines       10970    11318     +348     
==========================================
+ Hits         9260     9565     +305     
- Misses       1346     1402      +56     
+ Partials      364      351      -13     
Flag Coverage Δ
unittests 84.51% <69.65%> (+0.09%) ⬆️

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.

@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

- Add tests for FormatForCLI() with various error types
- Add tests for GetUserMessage() error extraction
- Add tests for FormatWithDetails() debug formatting
- Add tests for AsDownloadError() type assertion
- Add tests for IsDownloadError() type checking
- Add tests for SuggestAction() for all 18 error codes

Coverage improved from 0% to 85.5% for pkg/errors package
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

…and timeout

- Add test for rate limit with context cancellation
- Add test for rate limit with context timeout
- Improves coverage of error handling paths in singleDownload function
- Tests verify proper error propagation when rate limiting encounters context errors
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

)

- Add 14 new test cases covering error paths in plugin loader and manager
- Test all error codes: CodeInvalidPath, CodeStorageError, CodeValidationError, CodePluginError
- Covers Load, LoadFromSearchPath, DiscoverPlugins, UnloadPlugin, GetPluginByName, etc.
- All tests passing

Related to #39 - improving patch coverage from 56.98% toward 84.41% target
)

- Add 15 new test cases covering error paths in retry manager
- Test context cancellation, non-retryable errors, and max retries exhausted
- Cover ExecuteWithRetry, ExecuteWithRetryCallback, and ExecuteWithRetryAndStats
- Test edge cases in NextDelay and addJitter functions
- All tests passing

Related to #39 - improving patch coverage from 56.98% toward 84.41% target
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

Add 18 test cases covering all 5 helper functions that had 0% coverage:
- NewInvalidPathError: 0% → 100%
- NewPluginError: 0% → 100%
- NewConfigError: 0% → 100%
- NewValidationError: 0% → 100%
- NewStorageError: 0% → 100%

Overall pkg/errors coverage improved from 85.5% to 89.3% (+3.8%).

Tests cover:
- Error creation without underlying errors
- Error creation with non-retryable underlying errors
- Behavior when DownloadError's Retryable field is not propagated
- Message formatting and error code assignment
- Details field population
- Integration between different helper functions

All 43 packages passing.
- Add 20+ test cases covering all validation error paths
- Test ConfigLoader.Load error handling (invalid JSON, corrupted files)
- Test all validation methods (validateTimeouts, validateNetwork, validateStorage, validateOutputFormat)
- Test ConfigLoader.Save error handling (write permissions)
- Test error message quality and context preservation
- Coverage improvement: pkg/config 90% → 96% (+6%)
- All validation error paths now covered
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

- Add error path tests for ValidateURL (empty, malformed, missing scheme, unsupported scheme, missing host, localhost restriction)
- Add error path tests for ValidateDestination (empty, directory traversal, parent errors, destination is directory)
- Add error path tests for ValidateContentLength (invalid format, negative values)
- Add error path tests for parseIntValue (invalid characters, no digits, special characters)
- Add error path tests for ValidateFileSize, ValidateTimeout, ValidateChunkSize
- Improve pkg/validation coverage to 97.9%
- All tests passing with comprehensive error validation
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

- Skip Unix-style path tests in pkg/plugin on Windows
- Skip chmod permission tests in pkg/validation on Windows
- Windows has different permission models and path formats
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

The WriteToReadOnlyDirectory test relies on Unix chmod behavior which
doesn't work the same way on Windows. Skip this test on Windows platform
similar to existing validation error path tests.

Issue #39
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

- Add TestNewHotReloadManagerErrorPaths for watch directory errors
- Add TestUnloadPluginErrorPaths for plugin dependency conflicts
- Add TestReloadPluginErrorPaths for reload failure scenarios
- Add TestHandlePluginRemovalErrorPath for removal errors
- Add TestAddWatchDirectoryErrorPaths for directory validation

Coverage improvements:
- NewHotReloadManager: 100% (line 84 NewStorageError path covered)
- unloadPlugin: 100% (line 310 NewPluginError for dependents covered)
- handlePluginRemoval: 100%
- pkg/plugin package: 90.1% overall

Addresses -7.30% patch coverage impact from hotreload.go
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

…39)

- Remove NonexistentWatchDirectory test (addWatchDirectory creates dirs via MkdirAll)
- Remove NonexistentPath test (same reason - implementation creates directories)
- Fix LoadFromDirectory_InvalidPath test to use cross-platform paths
- All 93 plugin tests now passing on macOS
- Addresses Windows CI test failures in run 19208632504
@github-actions
Copy link

github-actions bot commented Nov 9, 2025

Performance Test Results

✅ No Performance Regression

View detailed results

All performance metrics are within acceptable ranges.

@forest6511 forest6511 merged commit 772aa63 into main Nov 9, 2025
22 of 23 checks passed
@forest6511 forest6511 deleted the feature/standardize-error-handling-issue-39 branch November 9, 2025 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[LOW] Standardize error handling with DownloadError

2 participants