{"record":{"id":"e912547c2d1208f1","repo":"benbjohnson/litestream","slug":"could-not-parse-time-s","errorCode":null,"errorMessage":"could not parse time: %s","messagePattern":"could not parse time: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":2419,"sourceCode":"\tif t, err := time.Parse(time.RFC3339Nano, value); err == nil {\n\t\treturn t, nil\n\t}\n\n\t// Try RFC3339 (without nanoseconds)\n\tif t, err := time.Parse(time.RFC3339, value); err == nil {\n\t\treturn t, nil\n\t}\n\n\t// Fall back to dateparser for relative expressions\n\tcfg := &dateparser.Configuration{\n\t\tCurrentTime: time.Now().UTC(),\n\t}\n\tresult, err := dateparser.Parse(cfg, value)\n\tif err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"invalid timestamp (expected RFC3339 or relative time like '5 minutes ago'): %s\", value)\n\t}\n\tif result.Time.IsZero() {\n\t\treturn time.Time{}, fmt.Errorf(\"could not parse time: %s\", value)\n\t}\n\treturn result.Time.UTC(), nil\n}\n\n// FileControl handles file control operations, specifically PRAGMA commands for time travel.\nfunc (f *VFSFile) FileControl(op int, pragmaName string, pragmaValue *string) (*string, error) {\n\tconst SQLITE_FCNTL_PRAGMA = 14\n\n\tif op != SQLITE_FCNTL_PRAGMA {\n\t\treturn nil, fmt.Errorf(\"unsupported file control op: %d\", op)\n\t}\n\n\tname := strings.ToLower(pragmaName)\n\n\tf.logger.Debug(\"file control\", \"pragma\", name, \"value\", pragmaValue)\n\n\tswitch name {\n\tcase \"litestream_txid\":","sourceCodeStart":2401,"sourceCodeEnd":2437,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L2401-L2437","documentation":"parseTimeValue() in vfs.go failed to produce a usable time for a PRAGMA litestream_time value. The value passed the RFC3339 attempts and dateparser.Parse() returned no error, but the resulting time.Time was the zero value, meaning dateparser recognized the string grammatically (or silently failed to match) but could not resolve it to an actual date. The library throws this because a zero time is not a valid time-travel target, so it is rejected with the raw input echoed back.","triggerScenarios":"A SQLite connection executes `PRAGMA litestream_time='<value>'` where <value> is not an RFC3339 timestamp and is not a relative expression dateparser can resolve, yet dateparser returns err==nil with a zero Time (e.g. empty-adjacent strings, strings with only a timezone or day name it half-recognizes, or locale-dependent formats it parses to nothing).","commonSituations":"Developers pass human-friendly but ambiguous values like 'yesterday', 'last week', bare dates ('2024-01-01'), or misspell RFC3339 timestamps ('2024-01-01 10:00:00' with a space instead of T); dateparser partially matches them and yields a zero time instead of an error, surfacing this message rather than the clearer 'invalid timestamp' error.","solutions":["Wrap the input in try/catch or error-check and print the exact value that failed","Rewrite the value as RFC3339, e.g. '2024-01-01T10:00:00Z' with a 'T' separator and timezone","Use a supported relative expression like '5 minutes ago' or '2 hours ago'","Use the keyword 'latest' to reset time travel to the newest state","Validate the timestamp string in application code before issuing the PRAGMA"],"exampleFix":"// before\nPRAGMA litestream_time = '2024-01-01 10:00:00';\n// after\nPRAGMA litestream_time = '2024-01-01T10:00:00Z';\n// or relative:\nPRAGMA litestream_time = '5 minutes ago';","handlingStrategy":"validation","validationCode":"// Go: validate before issuing PRAGMA litestream_time\nfunc validTimeTravelValue(v string) bool {\n    if strings.EqualFold(v, \"latest\") { return true }\n    if _, err := time.Parse(time.RFC3339Nano, v); err == nil { return true }\n    if _, err := time.Parse(time.RFC3339, v); err == nil { return true }\n    // relative forms: e.g. '5 minutes ago', '2 hours ago'\n    rel := regexp.MustCompile(`(?i)^\\d+\\s+(second|minute|hour|day|week|month|year)s?\\s+ago$`)\n    return rel.MatchString(v)\n}","typeGuard":"func isZeroTime(t time.Time) bool { return t.IsZero() }","tryCatchPattern":"// driver-level\n_, err := db.Exec(\"PRAGMA litestream_time = ?\", value)\nif err != nil && strings.Contains(err.Error(), \"could not parse time\") {\n    // fall back to a safe default\n    _, err = db.Exec(\"PRAGMA litestream_time = 'latest'\")\n}","preventionTips":["Always emit RFC3339 with 'T' separator and timezone (e.g. time.Now().UTC().Format(time.RFC3339))","Prefer 'latest' or simple '<N> <unit>s ago' relative expressions over free-form dates","Validate timestamps with time.Parse(RFC3339) in the app before issuing the PRAGMA","Avoid locale-dependent formats like '01/02/2024' or 'yesterday'"],"tags":["go","sqlite","vfs","pragma","time-parsing"],"backgroundTag":"invalid-date-format","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"}