{"record":{"id":"edb25a026a60eb7b","repo":"gastownhall/beads","slug":"db-getcustomtypes-w","errorCode":null,"errorMessage":"db: GetCustomTypes: %w","messagePattern":"db: GetCustomTypes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/config.go","lineNumber":175,"sourceCode":"\tfor rows.Next() {\n\t\tvar name string\n\t\tif err := rows.Scan(&name); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"db: GetCustomTypes: scan custom_types: %w\", err)\n\t\t}\n\t\tif name = strings.TrimSpace(name); name != \"\" {\n\t\t\tout = append(out, name)\n\t\t}\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"db: GetCustomTypes: read custom_types: %w\", err)\n\t}\n\treturn out, nil\n}\n\nfunc (r *configSQLRepositoryImpl) readCustomTypesConfig(ctx context.Context) ([]string, error) {\n\tvalue, err := r.GetConfig(ctx, \"types.custom\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: GetCustomTypes: %w\", err)\n\t}\n\treturn issueops.ParseTypesConfigValue(value), nil\n}\n\nfunc unionWithYAMLCustomTypes(dbTypes, yamlTypes []string) []string {\n\tif len(dbTypes) == 0 && len(yamlTypes) == 0 {\n\t\treturn nil\n\t}\n\tseen := make(map[string]struct{}, len(dbTypes)+len(yamlTypes))\n\tout := make([]string, 0, len(dbTypes)+len(yamlTypes))\n\tfor _, src := range [][]string{dbTypes, yamlTypes} {\n\t\tfor _, t := range src {\n\t\t\tt = strings.TrimSpace(t)\n\t\t\tif t == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif _, ok := seen[t]; ok {\n\t\t\t\tcontinue","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/config.go#L157-L193","documentation":"This error wraps a failure from GetConfig(ctx, \"types.custom\") — a SELECT on the config table — inside readCustomTypesTable's fallback path in GetCustomTypes. It is only reached when the custom_types table returned no rows, meaning the store is falling back to the legacy types.custom config string. The underlying cause is a driver/connection-level failure, since a missing key returns empty string without error.","triggerScenarios":"Calling GetCustomTypes on a store whose custom_types table is empty (or nonexistent), and the subsequent GetConfig(\"types.custom\") SELECT on the config table fails with a driver error (connection drop, cancelled context, server error).","commonSituations":"Legacy deployments that still store custom types in the config string; remote Dolt servers with flaky connectivity; context cancellation during fallback reads.","solutions":["Unwrap the error to see the underlying GetConfig/driver failure.","Reconnect or retry once the database connection is healthy.","Populate the custom_types table via bd config set types.custom ... so the fallback path (and this failure point) is avoided.","Check server health/logs if the config table itself is unreadable."],"exampleFix":"// before\nif err != nil {\n    return nil, err // opaque wrapped db: GetCustomTypes error\n}\n// after\nif err != nil {\n    log.Printf(\"custom types fallback read failed: %v\", err)\n    // inspect cause: errors.Is(err, context.Canceled), driver errors, etc.\n    return nil, err\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"types, err := store.GetCustomTypes(ctx)\nif err != nil {\n    var derr *driverError\n    if errors.As(err, &derr) {\n        log.Printf(\"custom-types fallback read failed: %v\", derr)\n        return defaultTypes, nil // or retry\n    }\n    return nil, err\n}","preventionTips":["Keep the custom_types table populated so the legacy fallback path is rarely used.","Classify wrapped causes with errors.Is/errors.As before deciding to retry or fail.","Monitor database connectivity health in deployment environments."],"tags":["database","config","fallback-read"],"backgroundTag":"row-iteration-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}