{"record":{"id":"42761044b3e75fcc","repo":"neondatabase/neon","slug":"invalid-time-for-travel-to","errorCode":null,"errorMessage":"Invalid time for travel_to: '{}'","messagePattern":"Invalid time for travel_to: '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/ctl/src/main.rs","lineNumber":157,"sourceCode":"        }\n        Commands::DrawTimeline {} => {\n            draw_timeline_dir::main()?;\n        }\n        Commands::AnalyzeLayerMap(cmd) => {\n            layer_map_analyzer::main(&cmd).await?;\n        }\n        Commands::PrintLayerFile(cmd) => {\n            if let Err(e) = read_pg_control_file(&cmd.path) {\n                println!(\n                    \"Failed to read input file as a pg control one: {e:#}\\n\\\n                    Attempting to read it as layer file\"\n                );\n                print_layerfile(&cmd.path).await?;\n            }\n        }\n        Commands::TimeTravelRemotePrefix(cmd) => {\n            let timestamp = humantime::parse_rfc3339(&cmd.travel_to)\n                .map_err(|_e| anyhow::anyhow!(\"Invalid time for travel_to: '{}'\", cmd.travel_to))?;\n\n            let done_if_after = if let Some(done_if_after) = &cmd.done_if_after {\n                humantime::parse_rfc3339(done_if_after).map_err(|_e| {\n                    anyhow::anyhow!(\"Invalid time for done_if_after: '{}'\", done_if_after)\n                })?\n            } else {\n                const SAFETY_MARGIN: Duration = Duration::from_secs(3);\n                tokio::time::sleep(SAFETY_MARGIN).await;\n                // Convert to string representation and back to get rid of sub-second values\n                let done_if_after = SystemTime::now();\n                tokio::time::sleep(SAFETY_MARGIN).await;\n                done_if_after\n            };\n\n            let timestamp = strip_subsecond(timestamp);\n            let done_if_after = strip_subsecond(done_if_after);\n\n            let Some(prefix) = validate_prefix(&cmd.prefix) else {","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/ctl/src/main.rs#L139-L175","documentation":"The time-travel-remote-prefix command requires --travel_to as an RFC 3339 timestamp and parses it with humantime::parse_rfc3339. Anything that is not full RFC 3339, such as date-only strings, slash-separated dates, or epoch numbers, is rejected with this error.","triggerScenarios":"Passing --travel-to \"2024/01/01\", \"2024-01-01\" without time and timezone, or an epoch integer; only forms like 2024-01-01T00:00:00Z parse.","commonSituations":"Timestamps generated with date +%F (date only) or locale-specific formats; hand-edited shell history.","solutions":["Use a full RFC 3339 timestamp with offset: 2024-01-01T12:34:56Z or 2024-01-01T12:34:56+00:00.","Generate timestamps in scripts with date -u +%Y-%m-%dT%H:%M:%SZ."],"exampleFix":"# before\npageserver_ctl time-travel-remote-prefix --travel-to \"2024/01/01 00:00\" ...\n\n# after\npageserver_ctl time-travel-remote-prefix --travel-to \"2024-01-01T00:00:00Z\" ...","handlingStrategy":"validation","validationCode":"// validate before invoking the ctl\nanyhow::ensure!(\n    humantime::parse_rfc3339(&travel_to).is_ok(),\n    \"travel_to must be RFC 3339, e.g. 2024-01-01T00:00:00Z\"\n);","typeGuard":"fn is_rfc3339(s: &str) -> bool {\n    humantime::parse_rfc3339(s).is_ok()\n}","tryCatchPattern":null,"preventionTips":["Generate timestamps with date -u +%Y-%m-%dT%H:%M:%SZ in scripts.","Always include the timezone (Z or +hh:mm); date-only values never parse."],"tags":["rust","neon","ctl","timestamp","rfc3339"],"backgroundTag":"invalid-timestamp-format","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}