stamparm/maltrail · error
trail reload failed ( )
Error message
trail reload failed ({e}) What it means
When the periodic trail update task returns Err(e), the sensor logs "trail reload failed ({e})" via output::log_error, increments the reloads_failed metric, and continues running with the previously loaded trails. It signals the trail refresh cycle itself failed (download/parse/load), not that trails were rejected for safety.
Solutions
- Read the ({e}) detail in the log to identify the exact failure (network vs IO vs parse).
- Check outbound connectivity/DNS from the sensor host and retry the update cycle.
- Validate the trails file at cfg.trails_file is readable and not corrupted (check permissions and size).
- Confirm the upstream trails URL is still valid and returning the expected format.
Defensive patterns
Strategy: retry
Validate before calling
// preflight the trails source before the cycle
let resp = reqwest::get(&trails_url).await?;
if !resp.status().is_success() { bail!("trails source returned {}", resp.status()); } Try / catch
match refresh_trails().await {
Err(e) => { log::warn!("trail reload failed ({e}); will retry next cycle"); schedule_retry_with_backoff(); }
Ok(_) => {}
} Prevention
- Alert on reloads_failed counter increases
- Run trail updates on a schedule with backoff and retry
- Keep the previous trails file so a failed update never leaves you empty
When it happens
Trigger: The trailupdate refresh future returns an error inside the periodic loop in run(): network failure downloading the trails archive, I/O error reading cfg.trails_file, or a parse failure of the downloaded format.
Common situations: Outbound connectivity loss or DNS failures on the sensor host; corrupt or truncated download; filesystem permission issues on the trails file path; upstream server returning an error page instead of the trails data.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/2072b33530b134aa.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/main.rs:579
{:.0}% floor); keeping the current set. If this drop is real, \
restart the sensor or lower 'TRAIL_RELOAD_MIN_RATIO'",
thousands(incoming),
thousands(current),
cfg_reload.trail_reload_min_ratio * 100.0
),
true,
);
} else {
reg_reload.trail_count.store(incoming, Ordering::Relaxed);
store_reload.publish(db);
reg_reload.trail_generation.store(store_reload.generation(), Ordering::Relaxed);
reg_reload.reloads_ok.fetch_add(1, Ordering::Relaxed);
cprintln!("[i] reloaded {} trails", thousands(stats.loaded as u64));
}
}
Err(e) => {
reg_reload.reloads_failed.fetch_add(1, Ordering::Relaxed);
output::log_error(&format!("trail reload failed ({e})"), true);
}
}
}
})
.ok();
}
// --- Prometheus endpoint ---------------------------------------------------
// Opt-in, and never fatal: a sensor that cannot bind its metrics port must still detect.
if !cfg.stats_address.is_empty() {
match maltrail_sensor::stats::spawn(&cfg.stats_address, registry.clone(), Instant::now()) {
Ok(bound) => {
if !args.quiet {
cprintln!("[i] metrics endpoint: http://{bound}/metrics");
}
}
Err(e) => {
ceprintln!("[!] metrics endpoint disabled: {e}");View on GitHub (pinned to 77cfb06d76)