{"record":{"id":"e197f02f7d65bca3","repo":"gastownhall/beads","slug":"db-setmetadata-s-w","errorCode":null,"errorMessage":"db: SetMetadata %s: %w","messagePattern":"db: SetMetadata (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/config.go","lineNumber":42,"sourceCode":"}\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 {\n\t\treturn \"\", fmt.Errorf(\"db: GetLocalMetadata %s: %w\", key, err)\n\t}\n\treturn value, nil\n}\n\nfunc (r *configSQLRepositoryImpl) SetLocalMetadata(ctx context.Context, key, value string) error {\n\tif _, err := r.runner.ExecContext(ctx, \"REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)\", key, value); err != nil {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/config.go#L24-L60","documentation":"SetMetadata writes a key/value pair into the metadata table using REPLACE INTO. This error wraps any failure of that Exec: database read-only or locked, metadata table missing, permission denied, connection loss, or context cancellation. Since metadata persists cross-machine state (sync keys, prefixes), a failure here usually blocks higher-level operations.","triggerScenarios":"ExecContext(\"REPLACE INTO metadata ...\") returns an error — SQLite/Dolt file locked by a concurrent writer, database opened read-only or on a read-only filesystem, schema missing the metadata table, or network failure to a remote Dolt server.","commonSituations":"Two bd processes writing simultaneously; running bd from a read-only mount or read-only replica; writing to a legacy database without the metadata table; disk full.","solutions":["Check the wrapped driver error for lock vs permission vs schema cause.","Ensure the DB file (or remote endpoint) is writable and no other process holds the lock.","Run migrations/doctor so the metadata table exists.","Free disk space / restore network connectivity, then retry the write."],"exampleFix":"// before\n// read-only replica\nconfigRepo.SetMetadata(ctx, \"issue_prefix\", \"bd\") // fails\n// after\nif !dbWritable(db) {\n    return fmt.Errorf(\"database is read-only; cannot set metadata\")\n}\nconfigRepo.SetMetadata(ctx, \"issue_prefix\", \"bd\")","handlingStrategy":"retry","validationCode":"// verify writability before metadata writes\nif err := runner.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"database unavailable: %w\", err)\n}\n// also ensure no competing writer holds the DB lock","typeGuard":"null","tryCatchPattern":"if err := configRepo.SetMetadata(ctx, key, value); err != nil {\n    if isLockedOrTransient(errors.Unwrap(err)) {\n        return retryWithBackoff(ctx, func() error { return configRepo.SetMetadata(ctx, key, value) })\n    }\n    return fmt.Errorf(\"cannot persist metadata %s: %w\", key, err)\n}","preventionTips":["Run only one bd writer per database at a time (or rely on file locking semantics).","Never point bd at a read-only mount/replica for mutating commands.","Keep disk space and connectivity healthy before sync operations.","Migrate legacy databases so the metadata table exists."],"tags":["go","sql","metadata","write-failure","database"],"backgroundTag":"database-write-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}