{"record":{"id":"a7e2de63382aad6c","repo":"benbjohnson/litestream","slug":"cannot-specify-index-timestamp-to-restore","errorCode":null,"errorMessage":"cannot specify index & timestamp to restore","messagePattern":"cannot specify index & timestamp to restore","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":613,"sourceCode":"}\n\n// Replica restores the database from a replica based on the options given.\n// This method will restore into opt.OutputPath, if specified, or into the\n// DB's original database path. It can optionally restore from a specific\n// replica or it will automatically choose the best one. Finally,\n// a timestamp can be specified to restore the database to a specific\n// point-in-time.\n//\n// When the replica contains both v0.3.x and LTX format backups, this method\n// compares snapshots from both formats and uses whichever has the better backup:\n// - With timestamp: uses the format with the most recent snapshot before timestamp\n// - Without timestamp: uses the format with the most recent backup overall\nfunc (r *Replica) Restore(ctx context.Context, opt RestoreOptions) (err error) {\n\t// Validate options.\n\tif opt.OutputPath == \"\" {\n\t\treturn fmt.Errorf(\"output path required\")\n\t} else if opt.TXID != 0 && !opt.Timestamp.IsZero() {\n\t\treturn fmt.Errorf(\"cannot specify index & timestamp to restore\")\n\t} else if opt.Follow && opt.TXID != 0 {\n\t\treturn fmt.Errorf(\"cannot use follow mode with -txid\")\n\t} else if opt.Follow && !opt.Timestamp.IsZero() {\n\t\treturn fmt.Errorf(\"cannot use follow mode with -timestamp\")\n\t} else if opt.IntegrityCheck != IntegrityCheckNone && opt.IntegrityCheck != IntegrityCheckQuick && opt.IntegrityCheck != IntegrityCheckFull {\n\t\treturn fmt.Errorf(\"unsupported integrity check mode: %d\", opt.IntegrityCheck)\n\t}\n\n\t// In follow mode, if the database already exists, attempt crash recovery\n\t// by reading the last applied TXID from the sidecar file.\n\tif opt.Follow {\n\t\tif _, statErr := os.Stat(opt.OutputPath); statErr == nil {\n\t\t\ttxid, readErr := ReadTXIDFile(opt.OutputPath)\n\t\t\tif readErr != nil {\n\t\t\t\treturn fmt.Errorf(\"read txid file for crash recovery: %w\", readErr)\n\t\t\t}\n\t\t\tif txid == 0 {\n\t\t\t\treturn fmt.Errorf(\"cannot resume follow mode: database exists but no -txid file found; delete the database to re-restore: %s\", opt.OutputPath)","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L595-L631","documentation":"Replica.Restore rejects mutually exclusive targeting: you may restore to a specific TXID or to a specific timestamp, but not both at once, since the two targets can conflict. Passing both a non-zero opt.TXID and a non-zero opt.Timestamp triggers this validation error before any restore work begins.","triggerScenarios":"Calling Restore with RestoreOptions where TXID != 0 and Timestamp is also set — e.g. code that fills both fields from user input without checking exclusivity, or CLI/config plumbing that passes both -txid and -timestamp through.","commonSituations":"UIs or scripts that forward all optional restore parameters unconditionally; users specifying both a transaction and a point-in-time; EnsureExists/Run callers combining stored TXID with a computed timestamp.","solutions":["Choose one target: set either TXID or Timestamp in RestoreOptions, not both.","Prefer Timestamp for point-in-time recovery; use TXID only when you know the exact transaction.","Sanitize option-building code to zero the other field when one is selected."],"exampleFix":"// before\nopt := litestream.RestoreOptions{TXID: txid, Timestamp: ts}\nerr := replica.Restore(ctx, opt) // fails\n\n// after\nopt := litestream.RestoreOptions{Timestamp: ts} // or TXID, not both\nerr := replica.Restore(ctx, opt)","handlingStrategy":"validation","validationCode":"if opt.TXID != 0 && !opt.Timestamp.IsZero() {\n    return fmt.Errorf(\"set either TXID or Timestamp, not both\")\n}","typeGuard":null,"tryCatchPattern":"if err := replica.Restore(ctx, opt); err != nil && strings.Contains(err.Error(), \"cannot specify index & timestamp\") {\n    // rebuild options with a single target and retry\n}","preventionTips":["Normalize restore inputs: zero out TXID when a timestamp is supplied and vice versa","In UIs/scripts, make txid and timestamp mutually exclusive controls","Validate RestoreOptions in a helper before invoking Restore"],"tags":["restore","validation","mutually-exclusive"],"backgroundTag":"mutually-exclusive-flags","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"}