{"id":"f2b25c2535b02236","repo":"rust-lang/cargo","slug":"expect-run-id-in-format-20060724t012128000z-16-c","errorCode":null,"errorMessage":"expect run ID in format `20060724T012128000Z-<16-char-hex>`, got `{s}`","messagePattern":"expect run ID in format `20060724T012128000Z-<16-char-hex>`, got `(.+?)`","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/util/logger.rs","lineNumber":201,"sourceCode":"    }\n}\n\nimpl std::fmt::Display for RunId {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let hash = &self.hash;\n        let timestamp = self.timestamp.strftime(Self::FORMAT);\n        write!(f, \"{timestamp}-{hash}\")\n    }\n}\n\nimpl std::str::FromStr for RunId {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let msg =\n            || format!(\"expect run ID in format `20060724T012128000Z-<16-char-hex>`, got `{s}`\");\n        let Some((timestamp, hash)) = s.rsplit_once('-') else {\n            anyhow::bail!(msg());\n        };\n\n        if hash.len() != 16 || !hash.chars().all(|c| c.is_ascii_hexdigit()) {\n            anyhow::bail!(msg());\n        }\n        let timestamp = jiff::civil::DateTime::strptime(Self::FORMAT, timestamp)\n            .and_then(|dt| dt.to_zoned(jiff::tz::TimeZone::UTC))\n            .map(|zoned| zoned.timestamp())\n            .with_context(msg)?;\n\n        Ok(RunId {\n            timestamp,\n            hash: hash.into(),\n        })\n    }\n}\n\n#[cfg(test)]","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/util/logger.rs#L183-L219","documentation":"RunId::from_str parses cargo run IDs of the form `<timestamp>-<16-hex-hash>` (e.g. `20060724T012128000Z-b0fd440798ab3cfb`). It splits on the last `-`; if there is no `-` at all (rsplit_once returns None) it bails with this message. The timestamp must match `%Y%m%dT%H%M%S%3fZ` and the hash must be exactly 16 ASCII hex digits.","triggerScenarios":"Parsing a run ID string that contains no `-` separator, e.g. a bare timestamp, a UUID, a git SHA, or any string without a hyphen, via RunId::from_str (e.g. reading a stale/foreign `CARGO_RUN_ID` or a log filename).","commonSituations":"A tooling script reads a directory name or env var expecting a cargo run ID but gets an unrelated identifier; a stale cache file from an older cargo format; manually constructing a run-id-like string and getting the format wrong.","solutions":["Ensure the string has the form `<UTC-timestamp>-<16-hex>` with a single trailing hyphen-separated hash.","Generate IDs from RunId::new and Display rather than hand-building strings.","If reading from a file/env var, validate the shape before parsing."],"exampleFix":"// before\nlet id: RunId = \"abc123\".parse()?; // no '-'\n\n// after\nlet id: RunId = \"20060724T012128000Z-b0fd440798ab3cfb\".parse()?;","handlingStrategy":"validation","validationCode":"fn is_valid_run_id_shape(s: &str) -> bool {\n    s.rsplit_once('-').is_some()\n}\n// complements the hash check below","typeGuard":"fn run_id_has_separator(s: &str) -> bool { s.contains('-') }","tryCatchPattern":"match s.parse::<RunId>() {\n    Err(e) if e.to_string().starts_with(\"expect run ID\") => {\n        eprintln!(\"run ID must be `<timestamp>-<16-hex>`; got {s:?}\");\n        return Err(e);\n    }\n    r => r,\n}","preventionTips":["Always obtain run IDs from RunId::new + Display, never hand-built strings.","Validate the `-` separator before parsing foreign/log-file IDs."],"tags":["run-id","parsing","logger","validation"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}