nilerr はエラーが発生しているにもかかわらず nil を返しているパターン(エラーの握りつぶし)を検出するツールです。
解決する問題 err != nil のチェック後に nil を返すと、エラーが静かに握りつぶされます。呼び出し側はエラーが発生したことを知る手段がなく、データの不整合や予期しない動作の原因になります。
1 2 3 4 5 6 7 8 func SaveUser (ctx context.Context, user *User) error { err := db.Insert(ctx, user) if err != nil { return nil } return nil }
1 2 3 4 5 6 7 8 func SaveUser (ctx context.Context, user *User) error { err := db.Insert(ctx, user) if err != nil { return fmt.Errorf("insert user %s: %w" , user.ID, err) } return nil }
設定 公式ドキュメント
設定オプションはありません。有効化するだけで動作します。
1 2 3 4 5 6 version: "2" linters: enable: - nilerr
オプション golangci-lint 経由では設定オプションはありません。
サンプル 検出例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 func GetConfig (path string ) (*Config, error ) { data, err := os.ReadFile(path) if err != nil { return nil , nil } return parseConfig(data) } func ProcessItem (ctx context.Context, id string ) error { item, err := fetchItem(ctx, id) if err != nil { slog.Error("fetch item" , "id" , id, "error" , err) return nil } return process(item) } func HandleError (err error ) error { if err != nil { switch { case errors.Is(err, ErrNotFound): return nil default : return err } } return nil }
修正例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func GetConfig (path string ) (*Config, error ) { data, err := os.ReadFile(path) if err != nil { return nil , fmt.Errorf("read config %s: %w" , path, err) } return parseConfig(data) } func ProcessItem (ctx context.Context, id string ) error { item, err := fetchItem(ctx, id) if err != nil { return fmt.Errorf("fetch item %s: %w" , id, err) } return process(item) } func HandleError (err error ) error { if err != nil { switch { case errors.Is(err, ErrNotFound): return fmt.Errorf("not found: %w" , err) default : return err } } return nil }
注意点
ログ出力してから nil を返すパターンも検出される。ログだけでは呼び出し側にエラーを伝えられないため、エラーを返すべき
意図的にエラーを無視したい場合は //nolint:nilerr // <理由> で明示的に抑制する
nilnil とは異なるチェック。nilnil は「nil, nil を同時に返す」パターンを検出し、nilerr は「err != nil なのに nil を返す」パターンを検出する
エラーハンドリングの方針として、ログ出力はエラーの最終的な処理場所(通常はアプリケーションの最上位層)で行い、中間層ではエラーをラップして伝播させるのが推奨
参考リンク