Skip to content

Enable more linters and fix existing issues#1627

Merged
dgageot merged 15 commits intodocker:mainfrom
dgageot:linters
Feb 7, 2026
Merged

Enable more linters and fix existing issues#1627
dgageot merged 15 commits intodocker:mainfrom
dgageot:linters

Conversation

@dgageot
Copy link
Member

@dgageot dgageot commented Feb 6, 2026

Newly Enabled Linters (31 added, 24 -> 55 total)

Linter Issues Action
asasalint 0 Enabled as-is
asciicheck 0 Enabled as-is
bidichk 0 Enabled as-is
decorder 0 Enabled as-is
dogsled 0 Enabled as-is
durationcheck 0 Enabled as-is
errorlint 18 Enabled, fixed all 18 (errors.Is/As, %w)
errname 3 Enabled, renamed 3 error types
exptostd 0 Enabled as-is
fatcontext 0 Enabled as-is
gocheckcompilerdir. 0 Enabled as-is
gochecksumtype 0 Enabled as-is
gomoddirectives 1 Enabled, configured replace-allow-list
gomodguard 0 Enabled as-is
goprintffuncname 0 Enabled as-is
grouper 0 Enabled as-is
iface 0 Enabled as-is
inamedparam 1 Enabled, added missing param name
loggercheck 0 Enabled as-is
mirror 1 Enabled, fixed unnecessary allocation
nilnesserr 0 Enabled as-is
nosprintfhostport 3 Enabled, switched to net.JoinHostPort
predeclared 0 Enabled as-is
reassign 0 Enabled as-is
recvcheck 5 Enabled, nolint on 5 Marshal/Unmarshal types
rowserrcheck 3 Enabled, fixed 3 missing rows.Err() checks
sloglint 0 Enabled as-is
testableexamples 0 Enabled as-is
unqueryvet 0 Enabled as-is
usetesting 0 Enabled as-is
wastedassign 3 Enabled, fixed 3 wasted assignments
whitespace 2 Enabled, fixed 2 extra newlines

Enable the following new linters:
- asasalint: Check for pass []any as any in variadic func(...any)
- asciicheck: Check identifiers for non-ASCII symbols
- bidichk: Check for dangerous unicode character sequences
- decorder: Check declaration order and count
- dogsled: Check assignments with too many blank identifiers
- durationcheck: Check for two durations multiplied together
- exptostd: Detect functions from golang.org/x/exp/ replaceable by std
- fatcontext: Detect nested contexts in loops and function literals
- gocheckcompilerdirectives: Check go compiler directive comments
- gochecksumtype: Run exhaustiveness checks on sum types
- gomodguard: Allow/blocklist for direct Go module dependencies
- goprintffuncname: Check printf-like functions are named with f
- grouper: Analyze expression groups
- iface: Detect incorrect use of interfaces
- loggercheck: Check key-value pairs for common logger libraries
- predeclared: Find code that shadows predeclared identifiers
- reassign: Check that package variables are not reassigned
- sloglint: Ensure consistent code style with log/slog
- testableexamples: Check if examples are testable
- usetesting: Report uses of functions with replacement in testing

Also alphabetically sort the linter list for maintainability.

Assisted-By: cagent
Detects SELECT * in SQL queries, encouraging explicit column selection.

Assisted-By: cagent
Fix: use builder.Write(formatted) instead of builder.WriteString(string(formatted))
to avoid unnecessary allocation in transcript.go.

Assisted-By: cagent
Fix unnecessary trailing newline in filesystem.go and unnecessary
leading newline in mcp.go.

Assisted-By: cagent
Reports constructs that check for err != nil but return a different
nil value error.

Assisted-By: cagent
Fix wasted assignments in oauth.go (use var instead of := for
variables that are immediately reassigned) and fast_renderer.go
(same pattern).

Assisted-By: cagent
Add parameter name to interface method Update(msg tea.Msg) in
layout.go Model interface.

Assisted-By: cagent
Rename error types to follow Go convention (ErrXxx for values, XxxError for types):
- ErrAutoModelFallback -> AutoModelFallbackError
- ErrKeychainNotAvailable -> KeychainNotAvailableError
- ErrPassNotAvailable -> PassNotAvailableError

Assisted-By: cagent
Use net.JoinHostPort instead of fmt.Sprintf for host:port URL
construction in DMR fallback URLs. This ensures correct handling
of IPv6 addresses.

Assisted-By: cagent
Add rows.Err() checks after row iteration loops in:
- memory/database/sqlite/sqlite.go (GetMemories)
- session/migrations.go (GetAppliedMigrations)
- session/store.go (GetSessionSummaries)

These are correctness bugs: without checking rows.Err(), I/O errors
during iteration would be silently ignored.

Assisted-By: cagent
Configure replace-allow-list to permit the intentional
github.com/charmbracelet/ultraviolet replacement.

Assisted-By: cagent
recvcheck flags types that mix pointer and value receivers.
The 5 flagged types (DeferConfig, RAGStrategyConfig in v2/v3/latest)
inherently require mixed receivers: MarshalYAML/MarshalJSON must use
value receivers so they're callable on slice elements, while
UnmarshalYAML/UnmarshalJSON must use pointer receivers to mutate.
Added //nolint:recvcheck with explanatory comments on these types.

Assisted-By: cagent
All 11 cases are deliberate patterns where err is checked but nil
is returned:
- Context cancellation treated as normal completion (acp, fake, mcp)
- Fallback to partial/default result on non-critical error (html, fsx)
- WalkDir callbacks skipping unreadable entries (skills, filesystem)
- Script errors returned as data, not Go errors (codemode)
- Non-JSON output skipping toon encoding (teamloader)

Assisted-By: cagent
Fix three categories of error handling issues:
- Use errors.Is instead of == for error comparison (6 fixes)
  io.EOF, sql.ErrNoRows, http.ErrServerClosed, context.Canceled
- Use errors.As instead of type assertion on errors (4 fixes)
  *exec.ExitError, *environment.RequiredEnvError, cli.RuntimeError
- Use %w instead of %v in fmt.Errorf for proper wrapping (8 fixes)
  api.go, eval.go, store.go, sqliteutil.go

Assisted-By: cagent
All 11 issues were intentional patterns, requiring 11 //nolint
directives with no actual code improvement.

Assisted-By: cagent
@dgageot dgageot requested a review from a team as a code owner February 6, 2026 17:09
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

✅ Review Complete - No Issues Found

This PR successfully enables 31 new linters and fixes all reported issues. After thorough analysis of the 700+ line diff across 34 files, no bugs were detected in the changed code.

Changes Verified

Error Handling (errorlint)

  • All type assertions correctly converted to errors.Is() and errors.As()
  • Proper error comparison for io.EOF, sql.ErrNoRows, http.ErrServerClosed, context.Canceled, etc.

Error Type Renames (errname)

  • ErrAutoModelFallbackAutoModelFallbackError
  • ErrKeychainNotAvailableKeychainNotAvailableError
  • ErrPassNotAvailablePassNotAvailableError
  • All references consistently updated throughout the codebase

Database Operations (rowserrcheck)

  • Added rows.Err() checks after iteration in all SQL query functions
  • Proper error handling in sqlite.go, store.go, and migrations.go

Error Wrapping

  • Changed %v to %w in fmt.Errorf() calls for better error chains
  • Applied in eval.go, api.go, store.go, sqlite.go

Network Operations (nosprintfhostport)

  • Correctly switched to net.JoinHostPort() for URL construction in dmr/client.go

Code Quality

  • Removed unnecessary string conversions (mirror)
  • Cleaned up wasted assignments (wastedassign)
  • Removed extra blank lines (whitespace)
  • Added parameter names to interface methods (inamedparam)
  • Added appropriate nolint comments for recvcheck linter

Summary

All linter fixes are correctly implemented with no functional regressions. The changes follow Go best practices and improve code quality, error handling, and maintainability.

Great work! 🎉

const Version = "0"

// Toolset represents a tool configuration
// Toolset represents a tool configuration.
Copy link
Contributor

Choose a reason for hiding this comment

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

lol this is really pedantic tbh

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, I need to take a look again. I want to catch issues. not this

Copy link
Member Author

Choose a reason for hiding this comment

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

Only a couple of comments were invalid. Let's try to live with it and revisit

@dgageot dgageot marked this pull request as draft February 7, 2026 07:25
@dgageot dgageot marked this pull request as ready for review February 7, 2026 08:36
@dgageot dgageot merged commit 4d7ae99 into docker:main Feb 7, 2026
18 of 20 checks passed
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Review Summary

Analyzed 34 files with linter fixes. Found 1 issue worth noting:

Nested error wrapping pattern: The code uses multiple %w verbs in a single fmt.Errorf call, which doesn't work as intended in Go. While this doesn't cause functional issues in the current usage, it's semantically incorrect for Go's error handling model.

Overall, the linter fixes look good - the error handling improvements (using errors.Is/errors.As instead of direct comparisons) are solid improvements.

// Return the original error if backup failed
slog.Error("Failed to backup database for recovery", "error", backupErr)
return nil, fmt.Errorf("migration failed: %w (backup also failed: %v)", err, backupErr)
return nil, fmt.Errorf("migration failed: %w (backup also failed: %w)", err, backupErr)
Copy link
Contributor

Choose a reason for hiding this comment

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

Issue: Multiple %w verbs in fmt.Errorf

The code uses fmt.Errorf("migration failed: %w (backup also failed: %w)", err, backupErr) but Go's fmt.Errorf only wraps the last error when multiple %w verbs are used.

This means:

  • errors.Unwrap() will only return backupErr, not err
  • errors.Is(returnedErr, err) will return false
  • The migration error (err) cannot be introspected via the error chain

While both error messages appear in the string (so user-visible info is preserved), this violates Go's error wrapping semantics.

Suggested fix:

return nil, fmt.Errorf("migration failed: %w (backup also failed: %v)", err, backupErr)

Or if you need to wrap both, create a custom error type or log one error separately.

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.

2 participants