{"record":{"id":"567ca7de82b69c64","repo":"nautechsystems/nautilus_trader","slug":"durations-seconds-request-parameter-must-contain-567ca7","errorCode":null,"errorMessage":"`durations_seconds` request parameter must contain values of at least one nanosecond, was {value}","messagePattern":"`durations_seconds` request parameter must contain values of at least one nanosecond, was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/time_range.rs","lineNumber":767,"sourceCode":"\nfn parse_time_range_duration(value: &Value) -> anyhow::Result<Option<DurationNanos>> {\n    if value.is_null() {\n        return Ok(None);\n    }\n\n    let seconds = value.as_f64().with_context(|| {\n        format!(\"`durations_seconds` request parameter must contain numbers or null, was {value}\")\n    })?;\n\n    if !seconds.is_finite() || seconds < 0.0 {\n        anyhow::bail!(\n            \"`durations_seconds` request parameter must contain non-negative finite values, was {value}\"\n        );\n    }\n\n    let nanos = seconds * NANOSECONDS_IN_SECOND as f64;\n    if nanos < 1.0 {\n        anyhow::bail!(\n            \"`durations_seconds` request parameter must contain values of at least one nanosecond, was {value}\"\n        );\n    }\n\n    if nanos > u64::MAX as f64 {\n        anyhow::bail!(\"`durations_seconds` value is too large, was {value}\");\n    }\n\n    Ok(Some(DurationNanos::new(nanos as u64)))\n}\n\n#[cfg(test)]\nmod tests {\n    use nautilus_common::messages::data::{RequestCommand, RequestInstrument};\n    use nautilus_core::{Params, UUID4, UnixNanos};\n    use nautilus_model::identifiers::{ClientId, InstrumentId};\n    use rstest::rstest;\n    use serde_json::json;","sourceCodeStart":749,"sourceCodeEnd":785,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/time_range.rs#L749-L785","documentation":"After converting seconds to nanoseconds, parse_time_range_duration requires the result to be at least 1 ns; smaller values (e.g. 0 or 1e-10 seconds) cannot be represented as a positive DurationNanos and are rejected. null entries remain allowed.","triggerScenarios":"Passing durations_seconds entries of 0 or sub-nanosecond values like 0.0000000001 (1e-10 s), so nanos < 1.0.","commonSituations":"Using 0 as a 'no duration' sentinel instead of null; fractional-second values below the nanosecond resolution of the engine; floating-point underflow from tiny computed durations.","solutions":["Use durations >= 1 nanosecond (1e-9 seconds)","Replace zero-duration entries with null to indicate 'no duration'","Round sub-nanosecond durations up to at least 1ns if a duration is truly required"],"exampleFix":"// before\njson!([\"durations_seconds\" => [0.0000000001]])\n// after\njson!([\"durations_seconds\" => [0.000000001]]) // 1 ns, or null for 'none'","handlingStrategy":"validation","validationCode":"fn at_least_one_ns(v: &serde_json::Value) -> bool {\n    matches!(v.as_f64(), Some(s) if s * 1e9 >= 1.0)\n}","typeGuard":"let ok = values.iter().all(|v| v.is_null() || at_least_one_ns(v));","tryCatchPattern":null,"preventionTips":["Use null, not 0, for 'no duration' entries","Remember the engine's resolution is nanoseconds; round up sub-ns durations"],"tags":["rust","validation","params","duration"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}