{"record":{"id":"ec24e30028acc938","repo":"jaegertracing/jaeger","slug":"failed-to-close-rows-w","errorCode":null,"errorMessage":"failed to close rows: %w","messagePattern":"failed to close rows: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/v2/clickhouse/tracestore/reader.go","lineNumber":100,"sourceCode":"\n\t\t\tvar errs []error\n\t\t\tfor rows.Next() {\n\t\t\t\tspan, scanErr := dbmodel.ScanRow(rows)\n\t\t\t\tif scanErr != nil {\n\t\t\t\t\terrs = append(errs, fmt.Errorf(\"failed to scan span row: %w\", scanErr))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\ttrace := dbmodel.FromRow(span)\n\t\t\t\tif !yield([]ptrace.Traces{trace}, nil) {\n\t\t\t\t\t_ = rows.Close()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tif rowsErr := rows.Err(); rowsErr != nil {\n\t\t\t\terrs = append(errs, fmt.Errorf(\"failed to read span rows: %w\", rowsErr))\n\t\t\t}\n\t\t\tif closeErr := rows.Close(); closeErr != nil {\n\t\t\t\terrs = append(errs, fmt.Errorf(\"failed to close rows: %w\", closeErr))\n\t\t\t}\n\t\t\tif err := errors.Join(errs...); err != nil {\n\t\t\t\tyield(nil, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (r *Reader) GetServices(ctx context.Context) ([]string, error) {\n\trows, err := r.conn.Query(ctx, sql.SelectServices)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to query services: %w\", err)\n\t}\n\n\tvar (\n\t\tservices []string\n\t\terrs     []error","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/clickhouse/tracestore/reader.go#L82-L118","documentation":"When rows.Close() returns an error after finishing iteration in Reader.GetTraces, it is appended to the error list and yielded as part of the joined error. clickhouse-go's Close can fail when releasing the connection if the connection is already broken, so this typically accompanies (or masks) an earlier streaming failure.","triggerScenarios":"GetTraces iteration completes (or breaks on a scan error) and the subsequent rows.Close() call fails because the connection was reset, the query was cancelled, or the underlying TCP conn is in a bad state.","commonSituations":"Network instability between jaeger and ClickHouse; context cancellation racing with query teardown; server-side kills (max_execution_time, memory limits) leaving the connection unusable for release.","solutions":["Inspect the joined error (errors.Join output) — the primary cause is usually the earlier wrapped error, not the close itself","Fix the underlying connection/timeout problem; the close error is secondary","Ensure queries honor context cancellation so teardown is clean","Keep clickhouse-go driver versions current, as older versions had close-error edge cases"],"exampleFix":"// before\ncancelledCtx, cancel := context.WithCancel(ctx)\ncancel()\nrows, _ := conn.Query(cancelledCtx, q) // close fails on cancelled conn\n// after\nrows, _ := conn.Query(ctx, q) // let iteration finish before teardown","handlingStrategy":"try-catch","validationCode":"// ensure clean cancellation semantics before querying\nctx, cancel := context.WithTimeout(ctx, queryTimeout)\ndefer cancel()","typeGuard":null,"tryCatchPattern":"err := doQuery(ctx)\nif err != nil {\n\t// close errors are joined; inspect each with errors.Unwrap\n\tfor e := err; e != nil; e = errors.Unwrap(e) {\n\t\tif strings.Contains(e.Error(), \"failed to close rows\") {\n\t\t\tlog.Printf(\"secondary close failure: %v\", e)\n\t\t\tbreak\n\t\t}\n\t}\n}","preventionTips":["Don't cancel contexts while rows are still being iterated; drain or close explicitly","Treat close errors as secondary — diagnose the primary wrapped error first","Keep clickhouse-go updated for teardown edge cases","Avoid server-side query kills by respecting resource limits"],"tags":["clickhouse","connection","resource-cleanup"],"backgroundTag":"rows-close-failed","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}