{"record":{"id":"b8ef22ddf988b0d1","repo":"neondatabase/neon","slug":"invalid-time-for-done-if-after","errorCode":null,"errorMessage":"Invalid time for done_if_after: '{}'","messagePattern":"Invalid time for done_if_after: '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/ctl/src/main.rs","lineNumber":161,"sourceCode":"        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 {\n                println!(\"specified prefix '{}' failed validation\", cmd.prefix);\n                return Ok(());\n            };\n            let config = RemoteStorageConfig::from_toml_str(&cmd.config_toml_str)?;","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/ctl/src/main.rs#L143-L179","documentation":"The optional --done-if-after argument of time-travel-remote-prefix is parsed with the same RFC 3339 parser (humantime::parse_rfc3339) as --travel_to. A value that is not full RFC 3339 is rejected with this error. When the flag is omitted, the command derives the value from the current time itself.","triggerScenarios":"Passing --done-if-after with a non-RFC 3339 value such as a date-only string or an epoch number.","commonSituations":"Filling both timestamp flags from the same script where one is formatted differently; locale-specific date output pasted into the command.","solutions":["Use a full RFC 3339 timestamp with timezone, for example 2024-01-01T00:00:00Z.","Generate the value with date -u +%Y-%m-%dT%H:%M:%SZ so both flags share one format.","If unsure, omit --done-if-after and let the command derive it from the current time."],"exampleFix":"# before\npageserver_ctl time-travel-remote-prefix --travel-to \"$TS\" --done-if-after \"Jan 1 12:00:00 2024\" ...\n\n# after\npageserver_ctl time-travel-remote-prefix --travel-to \"$TS\" --done-if-after \"2024-01-01T12:00:00Z\" ...","handlingStrategy":"validation","validationCode":"if let Some(done_if_after) = &cmd.done_if_after {\n    anyhow::ensure!(\n        humantime::parse_rfc3339(done_if_after).is_ok(),\n        \"done_if_after must be RFC 3339, e.g. 2024-01-01T00:00:00Z\"\n    );\n}","typeGuard":"fn is_rfc3339(s: &str) -> bool {\n    humantime::parse_rfc3339(s).is_ok()\n}","tryCatchPattern":null,"preventionTips":["Format both --travel-to and --done-if-after from the same RFC 3339 generator.","When the exact cutoff is not important, omit --done-if-after and let the command derive it."],"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"}