{"record":{"id":"05a05efe2201a3f8","repo":"quickwit-oss/quickwit","slug":"time-format-description-should-be-valid","errorCode":null,"errorMessage":"time format description should be valid","messagePattern":"time format description should be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-telemetry-exporters/src/logs.rs","lineNumber":36,"sourceCode":"use serde_json::{Map, Value};\nuse time::format_description::BorrowedFormatItem;\nuse tracing::field::{Field, Visit};\nuse tracing::{Event, Subscriber};\nuse tracing_subscriber::field::RecordFields;\nuse tracing_subscriber::fmt::FmtContext;\nuse tracing_subscriber::fmt::format::{\n    DefaultFields, Format, FormatEvent, FormatFields, Full, Json, JsonFields, Writer,\n};\nuse tracing_subscriber::fmt::time::UtcTime;\nuse tracing_subscriber::registry::LookupSpan;\n\n/// We do not rely on the RFC3339 implementation, because it has a nanosecond precision.\n/// See discussion here: https://github.com/time-rs/time/discussions/418\npub(crate) fn time_formatter() -> UtcTime<Vec<BorrowedFormatItem<'static>>> {\n    let time_format = time::format_description::parse_borrowed::<2>(\n        \"[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z\",\n    )\n    .expect(\"time format description should be valid\");\n    UtcTime::new(time_format)\n}\n\npub(crate) enum EventFormat<'a> {\n    Full(Format<Full, UtcTime<Vec<BorrowedFormatItem<'a>>>>),\n    Json(Format<Json>),\n    Ddg(DdgFormat),\n}\n\nimpl EventFormat<'_> {\n    /// Gets the log format from the environment variable `QW_LOG_FORMAT`.\n    pub(crate) fn get_from_env() -> Self {\n        match get_from_env_opt::<String>(\"QW_LOG_FORMAT\", false)\n            .as_deref()\n            .map(str::to_ascii_lowercase)\n            .as_deref()\n        {\n            Some(\"json\") => EventFormat::Json(tracing_subscriber::fmt::format().json()),","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-telemetry-exporters/src/logs.rs#L18-L54","documentation":"This panic fires when `time::format_description::parse_borrowed::<2>` fails to parse the hard-coded format string `[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z` used by the telemetry log timestamp formatter. The string is a compile-time constant in the source, so the panic can only occur if that constant was edited to an invalid format description (bad component syntax, invalid modifier, or exceeding the 2-item inline capacity... note the string parses as one item, so capacity is not the issue). It protects the logging subsystem from silently emitting malformed timestamps.","triggerScenarios":"Calling `time_formatter()` (directly, or via `get_from_env`/`capture_full_log` which configure the tracing subscriber) after someone modified the format string literal in quickwit-telemetry-exporters/src/logs.rs to an invalid `time` crate format description.","commonSituations":"A contributor edits the timestamp format to change precision or timezone representation and uses invalid `time`-crate syntax (e.g. `[subsecond digits:9]` misspelled, unknown component, wrong modifier); upgrading the `time` crate to a version that removed or renamed a format component.","solutions":["Check git history of quickwit/quickwit-telemetry-exporters/src/logs.rs — restore the original format string `[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z`","Validate your new format string with `time::format_description::parse_borrowed::<2>(...)` in a unit test before committing it","If a `time` crate upgrade broke it, consult the time-rs changelog for renamed/removed format components and fix the description accordingly","Use `time::macros::format_description!` instead of runtime parsing to turn this panic into a compile-time error"],"exampleFix":"// before (invalid component)\n\"[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:three]Z\"\n// after\n\"[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z\"","handlingStrategy":"validation","validationCode":"#[test]\nfn time_format_is_valid() {\n    time::format_description::parse_borrowed::<2>(\n        \"[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond digits:3]Z\",\n    ).expect(\"time format description should be valid\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer the `time::macros::format_description!` macro so invalid formats fail at compile time","Add a unit test that calls time_formatter() so edits to the format string are caught in CI","Validate any new format string in the time-rs playground or a scratch test before committing"],"tags":["rust","logging","timestamps","time-format"],"backgroundTag":"invalid-date-format","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}