chore(lint): enable errorlint and make error identity survive wrapping - #6985
Merged
Conversation
errorlint rejects the three ways an error check silently stops working once something in the chain wraps it: == comparison, a type assertion, and a %v verb in fmt.Errorf. 29 sites, most of them the io.Copy guard `err != io.EOF`. Three are more than mechanical: - pkg/validator: StructWithFields asserted err.(validator.ValidationErrors) unchecked. A non-struct argument makes Validate.Struct return InvalidValidationError instead, so the assertion panicked. It now reports the invalid structure with no fields. - pkg/errors: WithData matched its parent with a bare type assertion and returned nil on anything else, dropping the error. errors.As finds a wrapped Error instead of swallowing it. All eight callers pass a bare sentinel, so none change behaviour today. - pkg/revdial: the Listener-closed error formatted its cause with %v, so errors.Is could not reach it. It wraps now.
|
Claude finished @otavio's task in 1m 50s —— View job Code Review CompleteReviewed 16 files across code quality, security, testing, language patterns, and architecture — no new issues found. The code looks good as-is. Notes (non-blocking)I verified the parts of this diff that carry actual semantic weight, and they hold up:
To request another review round, comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Enables
errorlintand fixes the 29 sites it reports. It catches the three ways an error check silently stops working once anything in the chain wraps the error:==/!=comparison against a sentinel, a type assertion onerror, and%vwherefmt.Errorfshould use%w.Why
Task 5 of the linting ledger. This is the last batch in the series with real semantic weight rather than mechanical rewrites:
%vversus%wdecides whaterrors.Iscan reach, and a bare==against a sentinel is a check that passes review and then quietly stops matching the first time a caller wraps.Changes
Most of the 29 are one pattern: the
err != nil && err != io.EOFguard afterio.Copyin the SSH channel plumbing and the agent's session modes. Those are mechanical.Three are not:
pkg/validator:StructWithFieldsdid an uncheckederr.(validator.ValidationErrors).Validate.Structreturns*InvalidValidationErrorwhen handed a non-struct, so that assertion panicked. It now reports the structure invalid with an empty field map.pkg/errors:WithDatamatched its parent with a bare type assertion and returnednilfor anything else, dropping the error entirely.errors.Asfinds a wrappedErrorinstead of swallowing it. All eight callers pass a bare sentinel, so nothing changes today — this only removes a way to lose an error later.pkg/revdial: the listener-closed error formatted its cause with%v, soerrors.Iscould not reach it. It wraps now.server/api/store/pg/utils.goand the bun query hook switched on the error value; both areerrors.Ischains now.Testing
fromSQLErrorhas the table inserver/api/store/pg/utils_test.gocovering the wrapped and joined cases, including thatcontext.Canceledstill passes through unwrapped.Verified locally: lint clean across all six modules plus the agent under both
dockerandnativetags; builds clean; unit tests pass for every touched package. Theenrollment_e2etests fail in my container for want of a Docker socket and fail identically onmaster.