{"record":{"id":"8e1a044744e0bb7f","repo":"nautechsystems/nautilus_trader","slug":"event-slug-builder-assets-must-include-at-least-on","errorCode":null,"errorMessage":"event_slug_builder.assets must include at least one non-empty asset","messagePattern":"event_slug_builder\\.assets must include at least one non-empty asset","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/config.rs","lineNumber":122,"sourceCode":"        let now = SystemTime::now()\n            .duration_since(UNIX_EPOCH)\n            .map_err(|e| anyhow::anyhow!(\"system clock before Unix epoch: {e}\"))?\n            .as_secs();\n        self.build_event_slugs_at_unix_secs(now)\n    }\n\n    fn build_event_slugs_at_unix_secs(&self, unix_secs: u64) -> anyhow::Result<Vec<String>> {\n        if self.interval_mins == 0 {\n            anyhow::bail!(\"event_slug_builder.interval_mins must be positive\");\n        }\n\n        if self.periods == 0 {\n            anyhow::bail!(\"event_slug_builder.periods must be positive\");\n        }\n\n        let assets = self.normalized_assets();\n        if assets.is_empty() {\n            anyhow::bail!(\"event_slug_builder.assets must include at least one non-empty asset\");\n        }\n\n        let period_secs = self\n            .interval_mins\n            .checked_mul(60)\n            .ok_or_else(|| anyhow::anyhow!(\"event_slug_builder.interval_mins is too large\"))?;\n        let period_start = (unix_secs / period_secs) * period_secs;\n        let period_secs = i128::from(period_secs);\n        let period_start = i128::from(period_start);\n        let mut slugs = Vec::new();\n\n        for period in 0..self.periods {\n            let period_offset = i128::from(self.start_offset_periods) + i128::from(period);\n            let timestamp = period_start + period_offset * period_secs;\n            if timestamp < 0 {\n                anyhow::bail!(\"event_slug_builder offset resolves before the Unix epoch\");\n            }\n","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/config.rs#L104-L140","documentation":"Config validation in the Polymarket event-slug builder: after filtering blank entries the assets list must still contain at least one non-empty asset symbol to build event slugs from; an all-blank list is rejected.","triggerScenarios":"Building event slugs where assets is empty, or every configured asset is an empty/whitespace string so normalized_assets() returns an empty vec.","commonSituations":"Config file with `assets = []`; assets supplied via env var that is unset; accidentally passing empty strings instead of asset symbols.","solutions":["Provide at least one non-empty asset in event_slug_builder.assets (e.g. [\"BTC\"])","Trim/validate asset strings in config before building slugs","Check env/secret sources that feed the assets list for empty values"],"exampleFix":"// before\n[event_slug_builder]\nassets = []\n// after\n[event_slug_builder]\nassets = [\"BTC\", \"ETH\"]","handlingStrategy":"validation","validationCode":"let assets: Vec<_> = cfg.event_slug_builder.assets.iter().map(|a| a.trim()).filter(|a| !a.is_empty()).collect();\nassert!(!assets.is_empty(), \"assets must include at least one non-empty asset\");","typeGuard":null,"tryCatchPattern":"match builder.build_event_slugs() {\n    Ok(slugs) => use(slugs),\n    Err(e) => { log::error!(\"assets misconfigured: {e}\"); return Err(e); }\n}","preventionTips":["Trim and filter asset strings when loading config","Require at least one asset in config schema validation","Avoid sourcing assets from possibly-empty env vars without defaults"],"tags":["polymarket","config","validation"],"backgroundTag":"empty-required-field","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"}