{"record":{"id":"44a742759ddde931","repo":"nautechsystems/nautilus_trader","slug":"invalid-usize-for-limit","errorCode":null,"errorMessage":"Invalid `usize` for 'limit'","messagePattern":"Invalid `usize` for 'limit'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/mod.rs","lineNumber":954,"sourceCode":"    pub fn end(&self) -> Option<UnixNanos> {\n        let metadata = self.metadata.as_ref()?;\n        let end_str = metadata.get_str(\"end\")?;\n        Some(UnixNanos::from_str(end_str).expect(\"Invalid `UnixNanos` for 'end'\"))\n    }\n\n    /// Returns an [`Option<usize>`] parsed from the metadata `limit` field.\n    ///\n    /// # Panics\n    ///\n    /// This function panics if:\n    /// - The `limit` value contained in the metadata is invalid.\n    #[must_use]\n    pub fn limit(&self) -> Option<usize> {\n        let metadata = self.metadata.as_ref()?;\n        metadata.get_usize(\"limit\").or_else(|| {\n            metadata\n                .get_str(\"limit\")\n                .map(|s| s.parse::<usize>().expect(\"Invalid `usize` for 'limit'\"))\n        })\n    }\n}\n\nimpl PartialEq for DataType {\n    fn eq(&self, other: &Self) -> bool {\n        self.topic == other.topic\n    }\n}\n\nimpl Eq for DataType {}\n\nimpl PartialOrd for DataType {\n    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {\n        Some(self.cmp(other))\n    }\n}\n","sourceCodeStart":936,"sourceCodeEnd":972,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/mod.rs#L936-L972","documentation":"`Data::limit` prefers metadata[\"limit\"] as a usize; if that's absent it tries the string form and `.parse::<usize>()`, panicking with \"Invalid `usize` for 'limit'\" when the string isn't a valid non-negative integer. This catches stringified limits that can't round-trip to a count, including negatives and floats.","triggerScenarios":"Setting metadata[\"limit\"] to \"-1\", \"1.5\", \"1000 bars\", or an empty string and then calling `.limit()` on the Data object.","commonSituations":"Config files with annotated numeric values (e.g. \"limit: 1000 bars\"); Python code storing ints with formatting; negative limits intended as 'unlimited' but represented as strings.","solutions":["Set limit as a plain non-negative integer string, e.g. metadata[\"limit\"] = \"1000\"","Handle 'unlimited' by omitting the key (returns None) rather than a sentinel like \"-1\"","Validate the string parses with int() before storing it in metadata"],"exampleFix":"// before\nmetadata[\"limit\"] = \"-1\"  // unlimited sentinel — panics on parse\n// after\n# omit the key for unlimited, or:\nmetadata[\"limit\"] = \"1000\"","handlingStrategy":"validation","validationCode":"def validate_limit_metadata(metadata: dict) -> None:\n    raw = metadata.get(\"limit\")\n    if raw is not None:\n        value = int(raw)  # raises ValueError if malformed\n        if value < 0:\n            raise ValueError(\"limit must be a non-negative integer\")","typeGuard":"def is_valid_limit_str(s: str) -> bool:\n    return s.isdigit()","tryCatchPattern":"try:\n    limit = data.limit()\nexcept Exception as e:\n    logger.error(f\"malformed 'limit' metadata: {metadata.get('limit')!r}\")\n    raise","preventionTips":["Store limit as a plain non-negative integer string","Omit the key entirely for 'unlimited' instead of negative sentinels","Strip annotations/units from config values before storing in metadata"],"tags":["rust","panic","metadata","parsing","limit"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}