atuinsh/atuin · error
Failed to compute stats
Error message
Failed to compute stats
What it means
A panic from `.expect()` on the `Option` returned by `atuin_history::stats::compute` in `atuin wrapped` (wrapped.rs:348). `compute` does not return a `Result` — it returns `None` when, after filtering, `top.is_empty()` (stats.rs:286-288): every command in the supplied history was skipped by `stats.ignored_commands`, collapsed away by `common_prefix`/`interesting_command`, or reduced to an empty string so the `.windows(ngram_size)` n-gram count produced nothing. The empty-history case is already guarded earlier (wrapped.rs:320), so this panic fires only when the year has history entries but zero usable stats.
Source
Thrown at crates/atuin/src/command/client/wrapped.rs:348
let host_id = Settings::host_id().await?;
let alias_store = AliasStore::new(store, host_id, encryption_key);
alias_store
.aliases()
.await
.unwrap_or_default()
.into_iter()
.map(|a| (a.name, a.value))
.collect()
} else {
HashMap::new()
}
} else {
HashMap::new()
};
// Compute overall stats using existing functionality
let stats = compute(settings, &history, 10, 1).expect("Failed to compute stats");
let wrapped_stats = WrappedStats::new(settings, &stats, &history, &alias_map);
// Print wrapped format
print_wrapped_header(year);
println!("🎉 In {year}, you typed {} commands!", stats.total_commands);
println!(
" That's ~{} commands every day\n",
stats.total_commands / 365
);
println!("Your Top Commands:");
atuin_history::stats::pretty_print(stats.clone(), 1, theme);
println!();
print_fun_facts(&wrapped_stats, &stats, year);
Ok(())View on GitHub (pinned to 202f6ad98e)
Solutions
- Handle the `None` case gracefully instead of `.expect`: use `let Some(stats) = ... else { print a friendly 'no usable commands' message; return Ok(()) }`
- Review `stats.ignored_commands` and `common_prefix` in `~/.config/atuin/config.toml` and narrow the patterns
- Inspect the year's history for empty or env-only commands: `atuin search --before <end> --after <start> <cmd>` or query the sqlite DB, and clean/purge junk entries
- As a library fix, have `wrapped` skip the pretty-print block (or lower the filter) when `compute` returns `None`
Example fix
// before
let stats = compute(settings, &history, 10, 1).expect("Failed to compute stats");
// after
let Some(stats) = compute(settings, &history, 10, 1) else {
println!("No usable commands found for {year} — check 'stats.ignored_commands' and 'common_prefix' in your config");
return Ok(());
}; Defensive patterns
Strategy: fallback
Validate before calling
// Before computing, check the year yields at least one usable command
let usable = history.iter().any(|h| {
let c = atuin_history::stats::strip_leading_env_vars(h.command.trim());
!c.is_empty()
&& !settings.stats.ignored_commands.iter()
.any(|ig| ig == &atuin_history::stats::interesting_command(settings, c))
});
if !usable {
println!("No usable commands for {year} — check your stats ignore rules");
return Ok(());
} Type guard
// compute() itself is the guard — treat it as a checked operation:
let stats = match compute(settings, &history, 10, 1) {
Some(s) => s,
None => return Ok(()), // nothing reportable for this year
}; Try / catch
// Rust Option, not exception — use let-else so absence is a normal outcome:
let Some(stats) = compute(settings, &history, 10, 1) else {
println!("No usable commands found for {year}");
return Ok(());
}; Prevention
- Never `.expect`/`.unwrap` on Option-returning aggregation functions; empty aggregate results are a legitimate input state, not a bug
- Keep `stats.ignored_commands` and `common_prefix` patterns narrow, and remember they also shrink `atuin wrapped`/`atuin stats` output
- Purge or fix imported history entries with empty/env-assignment-only commands
- When adding features over `compute`, handle `None` explicitly in tests so the fallback branch is covered
When it happens
Trigger: Running `atuin wrapped <year>` (or the month-appropriate default year) where `db.range(start, end)` returns non-empty history but `compute(settings, &history, 10, 1)` yields `None`: e.g. every command matches an `ignored_commands`/`common_prefix` entry in config.toml, or entries whose command strings are empty (or only env-var prefixes) after `strip_leading_env_vars` and trimming, leaving no n-grams for `windows(1)`.
Common situations: An over-broad `stats.ignored_commands` or `common_prefix: ["*"]`-style config that filters the entire year; imported shell history containing blank/env-assignment-only entries; a year where the user only ran commands that Atuin's default prefix rules collapse to nothing.
Related errors
- failed to create client
- issue in stats previous query
- issue in stats next query
- issue in stats average query
- issue in stats exits query
AI-assisted analysis of atuinsh/atuin@202f6ad98e (2026-08-16).
Data as JSON: /api/errors/e4860e611b7bd3f5.
Report an issue: GitHub.