{"record":{"id":"a9dbf070394eeb08","repo":"benbjohnson/litestream","slug":"no-replica-configured","errorCode":null,"errorMessage":"no replica configured","messagePattern":"no replica configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db.go","lineNumber":694,"sourceCode":"func (db *DB) LastSuccessfulSyncAt() time.Time {\n\tdb.lastSuccessfulSyncMu.RLock()\n\tdefer db.lastSuccessfulSyncMu.RUnlock()\n\treturn db.lastSuccessfulSyncAt\n}\n\n// SyncStatus represents the current replication state of the database.\ntype SyncStatus struct {\n\tLocalTXID  ltx.TXID\n\tRemoteTXID ltx.TXID\n\tInSync     bool\n}\n\n// SyncStatus returns the current replication status of the database, comparing\n// the local transaction position against the remote replica position. The remote\n// position is queried from the replica storage, so this method may perform I/O.\nfunc (db *DB) SyncStatus(ctx context.Context) (SyncStatus, error) {\n\tif db.Replica == nil {\n\t\treturn SyncStatus{}, fmt.Errorf(\"no replica configured\")\n\t}\n\n\tlocalPos, err := db.Pos()\n\tif err != nil {\n\t\treturn SyncStatus{}, fmt.Errorf(\"local position: %w\", err)\n\t}\n\n\tremotePos, err := db.Replica.calcPos(ctx)\n\tif err != nil {\n\t\treturn SyncStatus{}, fmt.Errorf(\"remote position: %w\", err)\n\t}\n\n\treturn SyncStatus{\n\t\tLocalTXID:  localPos.TXID,\n\t\tRemoteTXID: remotePos.TXID,\n\t\tInSync:     localPos.TXID > 0 && localPos.TXID == remotePos.TXID,\n\t}, nil\n}","sourceCodeStart":676,"sourceCodeEnd":712,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L676-L712","documentation":"SyncStatus compares the local transaction position against the remote replica position, so it requires db.Replica to be configured. When the database was opened without a replica (local monitoring only), it returns the plain error 'no replica configured'.","triggerScenarios":"Calling db.SyncStatus(ctx) (library API) on a DB opened without a replica attached — e.g. config file with no [[replica]] section for the database, or a Replica-less DB constructed programmatically.","commonSituations":"Deploying a config where a database block exists but replication was never configured (or was commented out); calling SyncStatus in monitoring code against a DB used only for restore; version changes where replicas became optional.","solutions":["Add a replica section to the config for that database path and reload litestream","Attach a replica programmatically before calling SyncStatus","If the database is intentionally replica-less, guard the call: skip SyncStatus when db.Replica == nil and report a non-replicating status","Verify the correct config file was loaded (a default/minimal config may omit replicas)"],"exampleFix":"// before\nstatus, err := db.SyncStatus(ctx)\n// after: guard when replication may be absent\nif db.Replica == nil {\n    return SyncStatusNotReplicating, nil\n}\nstatus, err := db.SyncStatus(ctx)","handlingStrategy":"type-guard","validationCode":"// Check replica presence before calling SyncStatus\nif db.Replica == nil {\n    return SyncStatus{}, errors.New(\"db has no replica; skipping status check\")\n}","typeGuard":"func hasReplica(db *litestream.DB) bool { return db.Replica != nil }","tryCatchPattern":"if !hasReplica(db) {\n    return SyncStatusNone, nil\n}\nstatus, err := db.SyncStatus(ctx)\nif err != nil {\n    return SyncStatusUnknown, fmt.Errorf(\"sync status: %w\", err)\n}","preventionTips":["Include a [[replica]] section for every database you monitor","Add config validation at startup that errors on replica-less monitored DBs","In library code, always branch on db.Replica == nil before remote status calls"],"tags":["configuration","replica","api-misuse"],"backgroundTag":"missing-required-config","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}