Relatório de Erros
Apresente erros acionáveis para usuários de CLI com anyhow e miette.
Receita
use anyhow::Context;
fn read_config(path: &str) -> anyhow::Result<String> {
std::fs::read_to_string(path)
.with_context(|| format!("falha ao ler a configuração em {path}"))
}
fn main() -> anyhow::Result<()> {
let cfg = read_config("app.toml")?;
println!("carregado {cfg}");
Ok(())
}Quando usar isso: Binários de aplicação onde os usuários precisam de mensagens ricas em contexto, não erros tipados no estilo de biblioteca.
Exemplo Funcional
use miette::{miette, IntoDiagnostic, Result};
#[derive(Debug, thiserror::Error, Diagnostic)]
#[error("porta inválida: {0}")]
#[diagnostic(code(app::invalid_port))]
struct InvalidPort(u16);
fn parse_port(s: &str) -> Result<u16> {
let port: u16 = s.parse().into_diagnostic()?;
if port == 0 {
return Err(miette!(InvalidPort(port)));
}
Ok(port)
}
fn main() -> Result<()> {
let port = parse_port("0")?;
println!("escutando em {port}");
Ok(())
}O que isso demonstra:
anyhow::Contextadiciona contexto de localização a errosstdmiettefornece códigos de diagnóstico e relatórios formatadosthiserrordefine tipos de erro de domínio pequenosmainretornaResultpara saída não zero automática
Análise Detalhada
anyhow vs thiserror vs miette
| Crate | Papel |
|---|---|
anyhow | Result ergonômico em binários |
thiserror | Erros tipados em bibliotecas |
miette | Relatórios bonitos com spans de origem |
Diretrizes de Erro de CLI
- Um problema por mensagem de erro
- Diga o que falhou, por quê e como corrigir
- Imprima em stderr; nunca misture erros em stdout JSON
- Encadeie contexto ao cruzar limites de subsistema
Códigos de Saída
use std::process::ExitCode;
fn main() -> ExitCode {
if let Err(e) = run() {
eprintln!("{e:#}");
return ExitCode::FAILURE;
}
ExitCode::SUCCESS
}Use {:#} para a cadeia completa do anyhow.
Armadilhas
- Imprimir apenas
Display- Usuários perdem a cadeia de erros. Correção: Use{:#}oumiette::Report. - Panics em CLI - Stack traces feias para usuários. Correção: Retorne
Resulte reserve panics para bugs. - Bibliotecas usam anyhow - Chamadores não podem comparar tipos de erro. Correção: Bibliotecas usam
thiserror; binários envolvem comanyhow. - RUST_BACKTRACE verboso por padrão - Sobrecarrega usuários. Correção: Mostre backtrace apenas com
--verboseou dica de ambiente. - Vazamento de caminhos internos -
/home/ci/...confunde usuários. Correção: Remova ou relativize caminhos em mensagens de usuário.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Apenas thiserror | Bibliotecas com erros comparáveis | Binário de nível superior precisando de cadeias de contexto |
eprintln! simples | Scripts minúsculos | Pipelines multi-etapas precisando de contexto |
color-eyre | Ferramentas de desenvolvimento durante o desenvolvimento | CLIs de produção com dependência mínima |
FAQs
anyhow em bibliotecas?
Evite. Consumidores de biblioteca precisam de erros tipados. Use thiserror e deixe binários envolverem com anyhow.
Como adiciono códigos de erro?
Use miette::Diagnostic com um atributo code(...) para IDs de erro pesquisáveis.
Saída de erro JSON?
Defina uma struct ErrorResponse { code, message, details } e imprima JSON serde em caso de falha quando --json for definido.
Suprimir avisos, mas mostrar erros?
Avisos vão para stderr com o prefixo WARN:. Erros usam saída não zero e formatação distinta.
Erros localizados?
Use fluent ou rust-i18n para mensagens traduzidas. Mantenha os códigos de erro estáveis entre os locais.
Testar mensagens de erro?
Afirme sobre err.to_string() ou format!("{err:#}") em testes de integração.
Registrar erros e imprimi-los?
Registre detalhes completos com tracing::error!. Imprima um resumo curto para o usuário em stderr.
Múltiplos erros de uma vez?
Colete erros em um Vec e imprima todos antes de sair. Comum em linters e validadores.
Cadeias de "causado por"?
anyhow suporta .context() e #[source]. Cada camada adiciona detalhes relevantes para o operador.
miette sem nightly?
miette funciona em Rust estável. Habilite o recurso fancy para relatórios gráficos quando stderr for um TTY.
Relacionado
- Noções Básicas de CLI - códigos de saída
- clap - erros de validação
- Configuração e Ambiente - falhas de carregamento de configuração
- Melhores Práticas de CLI - mensagens acionáveis
Versões da Pilha: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.