{"record":{"id":"3e80ad8bb571fa58","repo":"gastownhall/beads","slug":"errreadonly","errorCode":"ErrReadOnly","errorMessage":"embeddeddolt: store is read-only","messagePattern":"embeddeddolt: store is read-only","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/embeddeddolt/readonly.go","lineNumber":17,"sourceCode":"package embeddeddolt\n\nimport \"errors\"\n\n// ErrReadOnly is returned when a write is attempted on a store opened\n// read-only — OpenReadOnly, or OpenForPreviewCommand for a --dry-run/--inspect\n// command.\n//\n// It is exported (and declared here, without a cgo build tag) because callers\n// outside this package have to be able to tell \"this store refuses writes by\n// construction\" apart from a real failure. The CLI's post-command\n// tip-metadata write is the case that forced it: that write is incidental\n// bookkeeping which read-only opens have always tolerated because\n// OpenForReadOnlyCommand is deliberately writable, and a store that genuinely\n// refuses it must not turn an otherwise successful command into a non-zero\n// exit after the fact.\nvar ErrReadOnly = errors.New(\"embeddeddolt: store is read-only\")\n","sourceCodeStart":1,"sourceCodeEnd":18,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/embeddeddolt/readonly.go#L1-L18","documentation":"ErrReadOnly is the sentinel for write attempts on an embedded Dolt store opened in read-only mode. Any mutating helper (withMutatingDBConn, withMutatingPinnedDBConn, ApplySchemaMigrations, etc.) returns it instead of performing the write. It is deliberately distinct from lifecycle failures so the CLI can suppress it for incidental post-command writes like tip metadata.","triggerScenarios":"Calling any write path (ApplySchemaMigrations, withMutatingDBConn/withMutatingPinnedDBConn closures, working-set/tip writes) on a store opened via a read-only open (e.g. preview/readonly open paths).","commonSituations":"Running a command against a repo opened read-only (locked database, preview mode, another process holds the DB) and the command or a post-command hook attempts a mutation.","solutions":["Re-open the store with a writable open path (OpenForReadOnlyCommand / OpenForWorkingSetReconcile exist precisely because normal opens must be writable)","Check errors.Is(err, embeddeddolt.ErrReadOnly) and skip/handle the incidental write instead of failing the command","Close other processes holding the database lock that forced read-only mode, then reopen"],"exampleFix":"// before\nif err := store.ApplySchemaMigrations(ctx); err != nil { return err }\n// after\nif err := store.ApplySchemaMigrations(ctx); err != nil {\n    if errors.Is(err, embeddeddolt.ErrReadOnly) {\n        return nil // read-only open: migrations not applicable\n    }\n    return err\n}","handlingStrategy":"type-guard","validationCode":"if store.ReadOnly() { // or check open mode before write calls\n    skipIncidentalWrites = true\n}","typeGuard":"func isReadOnlyErr(err error) bool { return errors.Is(err, embeddeddolt.ErrReadOnly) }","tryCatchPattern":"if err := doWrite(ctx, store); err != nil {\n    if errors.Is(err, embeddeddolt.ErrReadOnly) {\n        return nil // tolerate incidental write on read-only store\n    }\n    return err\n}","preventionTips":["Track the open mode (read-only vs writable) and route writes accordingly","Use errors.Is against the ErrReadOnly sentinel instead of string matching","Skip post-command bookkeeping writes when the store was opened read-only"],"tags":["go","embedded-dolt","read-only","sentinel-error"],"backgroundTag":"read-only-store","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}