{"record":{"id":"4fc9032dcf4be653","repo":"gastownhall/beads","slug":"db-getmetadata-s-w","errorCode":null,"errorMessage":"db: GetMetadata %s: %w","messagePattern":"db: GetMetadata (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/config.go","lineNumber":35,"sourceCode":"\nfunc NewConfigSQLRepository(runner Runner) domain.ConfigSQLRepository {\n\treturn &configSQLRepositoryImpl{runner: runner}\n}\n\ntype configSQLRepositoryImpl struct {\n\trunner Runner\n}\n\nvar _ domain.ConfigSQLRepository = (*configSQLRepositoryImpl)(nil)\n\nfunc (r *configSQLRepositoryImpl) GetMetadata(ctx context.Context, key string) (string, error) {\n\tvar value string\n\terr := r.runner.QueryRowContext(ctx, \"SELECT value FROM metadata WHERE `key` = ?\", key).Scan(&value)\n\tif errors.Is(err, sql.ErrNoRows) {\n\t\treturn \"\", nil\n\t}\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"db: GetMetadata %s: %w\", key, err)\n\t}\n\treturn value, nil\n}\n\nfunc (r *configSQLRepositoryImpl) SetMetadata(ctx context.Context, key, value string) error {\n\tif _, err := r.runner.ExecContext(ctx, \"REPLACE INTO metadata (`key`, value) VALUES (?, ?)\", key, value); err != nil {\n\t\treturn fmt.Errorf(\"db: SetMetadata %s: %w\", key, err)\n\t}\n\treturn nil\n}\n\nfunc (r *configSQLRepositoryImpl) GetLocalMetadata(ctx context.Context, key string) (string, error) {\n\tvar value string\n\terr := r.runner.QueryRowContext(ctx, \"SELECT value FROM local_metadata WHERE `key` = ?\", key).Scan(&value)\n\tif errors.Is(err, sql.ErrNoRows) {\n\t\treturn \"\", nil\n\t}\n\tif err != nil {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/config.go#L17-L53","documentation":"GetMetadata reads a single row from the shared metadata table by key. A missing key is not an error (it returns \"\", nil), so this wrapper only fires when the SELECT itself fails: database unavailable, metadata table missing (uninitialized/pre-migration schema), permission denied, or context cancellation. The failing key is embedded in the message for diagnosis.","triggerScenarios":"QueryRowContext(\"SELECT value FROM metadata WHERE `key` = ?\").Scan returns an error other than sql.ErrNoRows — e.g. corrupt/locked Dolt or SQLite file, metadata table absent in a fresh or legacy database, or the connection dropped mid-query.","commonSituations":"Running bd against a database created by an older version without the metadata table; read-only filesystem/permissions; network blip to a remote Dolt server; database locked by another writer.","solutions":["Inspect the wrapped cause (%w) for the concrete driver error.","Run bd doctor / migrations to ensure the metadata table exists in the target database.","Check database connectivity, file permissions, and that the DB isn't locked by another process.","Retry transient failures; treat empty-string (not error) as the signal for a missing key."],"exampleFix":"// before\nv, err := configRepo.GetMetadata(ctx, \"issue_prefix\") // fails on legacy DB\n// after\nif err := migrate.EnsureSchema(db); err != nil {\n    return err\n}\nv, err := configRepo.GetMetadata(ctx, \"issue_prefix\")","handlingStrategy":"fallback","validationCode":"// verify DB reachability and schema before depending on metadata\nif err := runner.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"database unavailable: %w\", err)\n}","typeGuard":"null","tryCatchPattern":"v, err := configRepo.GetMetadata(ctx, key)\nif err != nil {\n    if strings.Contains(err.Error(), \"no such table\") {\n        // run bd doctor / migrations to create the metadata table\n    }\n    return fmt.Errorf(\"metadata read failed for %s: %w\", key, err)\n}\nif v == \"\" {\n    // key absent: use default — this is NOT an error\n}","preventionTips":["Remember missing keys return (\"\", nil); only real SQL failures return this error.","Keep schema migrated so the metadata table exists.","Treat empty string as the default-value signal instead of error-based checks.","Retry transient failures with backoff."],"tags":["go","sql","metadata","database","query-failure"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}