diff --git a/.golangci.yml b/.golangci.yml index 231e63e79..42cb0dea5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -19,9 +19,15 @@ version: "2" linters: default: none enable: + - errcheck - misspell - nlreturn - perfsprint + settings: + errcheck: + exclude-functions: + - (github.com/pterm/pterm.TablePrinter).Render + - (github.com/pterm/pterm.TreePrinter).Render exclusions: generated: lax presets: @@ -29,6 +35,10 @@ linters: - common-false-positives - legacy - std-error-handling + rules: + - linters: + - errcheck + path: _test\.go$ paths: - third_party$ - builtin$ diff --git a/catalog/rest/rest.go b/catalog/rest/rest.go index 6c1f92b9d..0a860699a 100644 --- a/catalog/rest/rest.go +++ b/catalog/rest/rest.go @@ -357,10 +357,15 @@ func doPostAllowNoContent[Payload, Result any](ctx context.Context, baseURI *url func handleNon200(rsp *http.Response, override map[int]error) error { var e errorResponse - dec := json.NewDecoder(rsp.Body) - dec.Decode(&struct { - Error *errorResponse `json:"error"` - }{Error: &e}) + // Only try to decode if there's a body (HEAD requests don't have one) + if rsp.ContentLength != 0 { + decErr := json.NewDecoder(rsp.Body).Decode(&struct { + Error *errorResponse `json:"error"` + }{Error: &e}) + if decErr != nil && decErr != io.EOF { + return fmt.Errorf("%w: failed to decode error response: %s", ErrRESTError, decErr.Error()) + } + } if override != nil { if err, ok := override[rsp.StatusCode]; ok { @@ -569,7 +574,10 @@ func (r *Catalog) fetchAccessToken(cl *http.Client, creds string, opts *options) switch rsp.StatusCode { case http.StatusUnauthorized, http.StatusBadRequest: - defer rsp.Request.GetBody() + defer func() { + _, _ = io.Copy(io.Discard, rsp.Body) + _ = rsp.Body.Close() + }() dec := json.NewDecoder(rsp.Body) var oauthErr oauthErrorResponse if err := dec.Decode(&oauthErr); err != nil { diff --git a/catalog/sql/sql.go b/catalog/sql/sql.go index 1e4a8ecde..9bbbfe2a3 100644 --- a/catalog/sql/sql.go +++ b/catalog/sql/sql.go @@ -154,7 +154,7 @@ type sqlIcebergNamespaceProps struct { } func withReadTx[R any](ctx context.Context, db *bun.DB, fn func(context.Context, bun.Tx) (R, error)) (result R, err error) { - db.RunInTx(ctx, &sql.TxOptions{ReadOnly: true}, func(ctx context.Context, tx bun.Tx) error { + err = db.RunInTx(ctx, &sql.TxOptions{ReadOnly: true}, func(ctx context.Context, tx bun.Tx) error { result, err = fn(ctx, tx) return err diff --git a/manifest.go b/manifest.go index c02c79dab..f3f73ac0d 100644 --- a/manifest.go +++ b/manifest.go @@ -1026,7 +1026,9 @@ func constructPartitionSummaries(spec PartitionSpec, schema *Schema, partitions for _, part := range partitions { for i, field := range partType.FieldList { - fieldStats[i].update(part[field.ID]) + if err := fieldStats[i].update(part[field.ID]); err != nil { + return nil, fmt.Errorf("error updating field stats for partition %d: %s: %s", i, field.Name, err) + } } }