{"record":{"id":"c3aeecd2a0a125b6","repo":"stamparm/maltrail","slug":"trail-update-unavailable-reason","errorCode":null,"errorMessage":"trail update unavailable: {reason}","messagePattern":"trail update unavailable: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"sensor/src/main.rs","lineNumber":1006,"sourceCode":"            }\n        }\n        trailupdate::Outcome::Disabled => {\n            if !quiet && startup {\n                cprintln!(\n                    \"[i] trail updates disabled ('DISABLE_TRAIL_UPDATES'); using '{}' as-is\",\n                    cfg.trails_file.display()\n                );\n                warn_if_trails_are_stale(cfg);\n            }\n        }\n        trailupdate::Outcome::Unavailable(reason) => {\n            ceprintln!(\"[!] cannot update trails: {reason}\");\n            ceprintln!(\n                \"[?] the sensor needs Maltrail's own updater (core/update.py) to refresh '{}'; \\\n                 without it, IOCs added since that file was written are NOT detected\",\n                cfg.trails_file.display()\n            );\n            output::log_error(&format!(\"trail update unavailable: {reason}\"), true);\n            warn_if_trails_are_stale(cfg);\n        }\n        trailupdate::Outcome::Failed(reason) => {\n            ceprintln!(\"[!] trail update failed ({reason}); continuing with the existing trails\");\n            output::log_error(&format!(\"trail update failed: {reason}\"), true);\n            warn_if_trails_are_stale(cfg);\n        }\n    }\n}\n\n/// Loudly flag a trails file older than one update period — the failure mode that cost a live\n/// detection: an old file looks perfectly healthy while the sensor quietly misses new IOCs.\nfn warn_if_trails_are_stale(cfg: &Config) {\n    let Some(age) = trailupdate::trails_age_secs(&cfg.trails_file) else {\n        ceprintln!(\"[!] no trails file at '{}' - the sensor will detect NOTHING\", cfg.trails_file.display());\n        return;\n    };\n    if age > cfg.update_period.max(1) {","sourceCodeStart":988,"sourceCodeEnd":1024,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/sensor/src/main.rs#L988-L1024","documentation":"The trail update subsystem returned Outcome::Unavailable(reason): Maltrail's own updater (core/update.py) is absent or cannot be used, so the Rust sensor cannot refresh the trails file. It logs \"trail update unavailable: {reason}\" and, via warn_if_trails_are_stale, flags a trails file older than one update period — IOCs added after the file was written will not be detected.","triggerScenarios":"refresh_trails in run() receives trailupdate::Outcome::Unavailable(reason), typically when core/update.py does not exist next to the sensor installation, or the update mechanism cannot be invoked for the configured cfg.trails_file.","commonSituations":"Deploying only the Rust sensor binary without the Maltrail Python core directory; installing from a package that omits core/update.py; moving the binary away from the repository checkout so the updater path no longer resolves.","solutions":["Install or restore core/update.py alongside the sensor so Maltrail's own updater is available.","Re-run the deployment from a full Maltrail checkout/package including the core directory.","Manually refresh the trails file (download from upstream) and restart the sensor as a stopgap.","Keep warn_if_trails_are_stale alerts visible and monitor trails file mtime until the updater is restored."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"import os\nif not os.path.exists('core/update.py'):\n    print('core/update.py missing: trail refresh will be unavailable')","typeGuard":"fn updater_available(core_dir: &Path) -> bool { core_dir.join(\"update.py\").is_file() }","tryCatchPattern":"match refresh_trails().await {\n    Outcome::Unavailable(reason) => { log_unavailable(&reason); manual_trails_refresh(); }\n    _ => {}\n}","preventionTips":["Deploy the Rust sensor from the full Maltrail tree, not the bare binary","Add a packaging check that core/update.py ships with the sensor","Monitor trails file mtime and warn when older than one update period"],"tags":["rust","trails","updater","deployment"],"backgroundTag":"missing-dependency","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}