{"record":{"id":"9af96379b195a76d","repo":"benbjohnson/litestream","slug":"calc-pos-w","errorCode":null,"errorMessage":"calc pos: %w","messagePattern":"calc pos: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":187,"sourceCode":"\n\t// Clear last position if if an error occurs during sync.\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tr.mu.Lock()\n\t\t\tr.pos = ltx.Pos{}\n\t\t\tr.mu.Unlock()\n\t\t}\n\t}()\n\n\tif err := ctx.Err(); err != nil {\n\t\treturn result, context.Cause(ctx)\n\t}\n\n\t// Calculate current replica position, if unknown.\n\tif r.Pos().IsZero() {\n\t\tpos, err := r.calcPos(ctx)\n\t\tif err != nil {\n\t\t\treturn result, fmt.Errorf(\"calc pos: %w\", err)\n\t\t}\n\t\tr.SetPos(pos)\n\t}\n\n\t// Find current position of database.\n\tdpos, err := r.db.Pos()\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"cannot determine current position: %w\", err)\n\t} else if dpos.IsZero() {\n\t\treturn result, errReplicaWaitForData\n\t}\n\n\tr.Logger().Debug(\"replica sync\",\n\t\tslog.Group(\"txid\",\n\t\t\tslog.String(\"replica\", r.Pos().TXID.String()),\n\t\t\tslog.String(\"db\", dpos.TXID.String()),\n\t\t))\n","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L169-L205","documentation":"During the first sync of a replica, syncOnce must determine the replica's current TXID position by listing remote LTX files (calcPos). If that discovery fails — unreadable/missing LTX header, listing error, or no usable files — the error is wrapped as 'calc pos'. Litestream cannot know where the replica stands and aborts the sync.","triggerScenarios":"First sync after registering a replica when calcPos cannot read the latest LTX header: remote listing fails (403/404), the newest LTX file is corrupt/truncated, or the replica path contains no valid LTX files.","commonSituations":"Fresh replica pointing at an empty bucket path; remote files truncated by a failed earlier upload; credentials allowing listing but not reading; network blip during the initial position discovery. Also surfaces in TestReplica_SyncOnceLimitsLTXFiles when fixtures are malformed.","solutions":["Inspect the wrapped error: if listing failed, fix credentials/region (see OSS GET/LIST errors); if a header is corrupt, the remote copy is damaged.","Run 'litestream ltx -level all' / 'litestream replicas' against the replica to see what files exist remotely.","For a genuinely empty/invalid remote state, run 'litestream reset <db>' to clear local LTX state and re-sync from scratch (or enable the auto-recover replica option to do this automatically).","If the latest LTX file is truncated, restore from an earlier complete generation and re-establish replication."],"exampleFix":"// before\nreplicas:\n  - type: oss\n    bucket: my-bucket\n    path: db/ltx\n// after (auto-recover clears bad local LTX state and re-syncs)\nreplicas:\n  - type: oss\n    bucket: my-bucket\n    path: db/ltx\n    auto-recover: true","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := replica.Sync(ctx); err != nil && strings.Contains(err.Error(), \"calc pos\") {\n    // clear bad local LTX state and resync\n    if rerr := resetAndResync(ctx); rerr != nil { return rerr }\n}","preventionTips":["Enable the auto-recover replica option so bad local LTX state resets automatically on position errors.","Monitor 'litestream replicas' output for zero/unknown TXID after startup.","Don't manually delete or edit LTX objects in the replica bucket.","Keep credentials valid for both LIST and GET so initial position discovery can succeed."],"tags":["replication","sync","position","ltx"],"backgroundTag":"empty-result-set","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}