{"record":{"id":"6482d4e6a4eed387","repo":"jaegertracing/jaeger","slug":"failed-to-scan-row-w-6482d4","errorCode":null,"errorMessage":"failed to scan row: %w","messagePattern":"failed to scan row: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/clickhouse/tracestore/reader.go","lineNumber":123,"sourceCode":"\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\n\t)\n\tfor rows.Next() {\n\t\tvar service dbmodel.Service\n\t\tif scanErr := rows.ScanStruct(&service); scanErr != nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"failed to scan row: %w\", scanErr))\n\t\t\tbreak\n\t\t}\n\t\tservices = append(services, service.Name)\n\t}\n\tif rowsErr := rows.Err(); rowsErr != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to read service rows: %w\", rowsErr))\n\t}\n\tif closeErr := rows.Close(); closeErr != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to close rows: %w\", closeErr))\n\t}\n\tif err := errors.Join(errs...); err != nil {\n\t\treturn nil, err\n\t}\n\treturn services, nil\n}\n\nfunc (r *Reader) GetOperations(\n\tctx context.Context,","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/clickhouse/tracestore/reader.go#L105-L141","documentation":"While iterating service rows, GetServices scans each row into a dbmodel.Service via rows.ScanStruct; if the scan fails (schema mismatch, NULL in a non-nullable field, wrong column types), the error is appended and iteration breaks. The wrapped error identifies the offending column and Go type.","triggerScenarios":"Calling GetServices against a services/name table whose columns don't match dbmodel.Service's fields — e.g. after a schema rename, or a NULL service name in a table expecting non-null String.","commonSituations":"Version skew between jaeger code and the applied ClickHouse schema; manually altered tables; data imported from another backend with different nullability conventions.","solutions":["Run the schema migrations matching your jaeger version so the services table matches dbmodel.Service","Check the wrapped error for the failing column and fix its type/nullability","Clean or backfill rows containing NULLs where the struct expects values","Re-create the services aggregation table if it was hand-modified"],"exampleFix":"// before\nservice_name Nullable(String) -- ScanStruct into string fails on NULL\n// after\nservice_name String -- with NOT NULL, per jaeger schema","handlingStrategy":"try-catch","validationCode":"// verify the services table schema matches expectations\ncols, err := conn.Query(ctx, \"DESCRIBE TABLE service_names\")\n// check service_name column is non-nullable String","typeGuard":null,"tryCatchPattern":"services, err := reader.GetServices(ctx)\nif err != nil {\n\tif strings.Contains(err.Error(), \"failed to scan row\") {\n\t\tlog.Printf(\"service_names schema mismatch: %v\", err) // fix schema, don't retry\n\t}\n\treturn err\n}","preventionTips":["Keep the applied schema version aligned with the jaeger binary version","Declare service-name columns as non-nullable String per the official schema","Validate imported/external data for NULLs before inserting into jaeger tables","Add a CI check that DESCRIBE output matches the expected schema DDL"],"tags":["clickhouse","schema","deserialization","scan"],"backgroundTag":"row-scan-type-mismatch","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}