---
title: "Cheatsheet: Error Handling em Zig"
url: "https://ziglang.com.br/cheatsheets/cheatsheet-error-handling-em-zig/"
markdown_url: "https://ziglang.com.br/cheatsheets/cheatsheet-error-handling-em-zig.MD"
description: "Referência rápida para tratamento de erros em Zig: error sets, error unions, try, catch, errdefer e padrões de erro. Guia completo em português."
date: "2026-02-21"
author: "Zig Brasil"
---

# Cheatsheet: Error Handling em Zig

Referência rápida para tratamento de erros em Zig: error sets, error unions, try, catch, errdefer e padrões de erro. Guia completo em português.


# Cheatsheet: Error Handling em Zig

O sistema de erros de Zig é uma das características mais distintas da linguagem. Em vez de exceções, Zig usa **error unions** que são verificados pelo compilador.

## Conjuntos de Erros (Error Sets)

```zig
// Definir conjunto de erros
const FileError = error{
    ArquivoNaoEncontrado,
    PermissaoNegada,
    DiskCheio,
};

const NetworkError = error{
    Timeout,
    ConexaoRecusada,
    DnsNaoResolvido,
};

// Combinar conjuntos de erros
const AppError = FileError || NetworkError;

// anyerror — qualquer erro possível
fn funcaoGenerica() anyerror!void {
    // pode retornar qualquer tipo de erro
}
```

## Error Unions

```zig
// Error union: tipo que pode ser erro ou valor
fn dividir(a: f64, b: f64) error{DivisaoPorZero}!f64 {
    if (b == 0) return error.DivisaoPorZero;
    return a / b;
}

// Com anyerror (inferido)
fn abrir(path: []const u8) !std.fs.File {
    return std.fs.cwd().openFile(path, .{});
}

// Retornar void com possível erro
fn salvar(dados: []const u8) !void {
    const file = try std.fs.cwd().createFile("output.txt", .{});
    defer file.close();
    try file.writeAll(dados);
}
```

## try — Propagar Erros

```zig
// try desempacota o valor ou retorna o erro imediatamente
fn processar() !i32 {
    const arquivo = try abrirArquivo();  // propaga erro se falhar
    defer arquivo.close();
    const dados = try lerDados(arquivo);  // propaga erro se falhar
    return try parsear(dados);             // propaga erro se falhar
}

// Equivalente a:
fn processarExplicito() !i32 {
    const arquivo = abrirArquivo() catch |err| return err;
    defer arquivo.close();
    const dados = lerDados(arquivo) catch |err| return err;
    return parsear(dados) catch |err| return err;
}
```

## catch — Tratar Erros

```zig
// catch com valor padrão
const valor = funcaoQuePoderFalhar() catch 0;

// catch com bloco
const valor2 = funcaoQuePoderFalhar() catch |err| blk: {
    std.log.err("Falha: {}\n", .{err});
    break :blk valorPadrao;
};

// catch com retorno
const valor3 = funcaoQuePoderFalhar() catch |err| {
    return err;  // propagar o erro
};

// catch unreachable (assert que não falha)
const valor4 = funcaoQuePoderFalhar() catch unreachable;

// catch com switch no erro
const resultado = operacao() catch |err| switch (err) {
    error.Timeout => {
        std.log.warn("Timeout, tentando novamente...\n", .{});
        return operacao() catch |e| return e;
    },
    error.ConexaoRecusada => {
        std.log.err("Servidor indisponível\n", .{});
        return err;
    },
    else => return err,
};
_ = resultado;
```

## if com Error Unions

```zig
const resultado: anyerror!i32 = calcular();

// Desempacotar com if
if (resultado) |valor| {
    std.debug.print("Sucesso: {}\n", .{valor});
} else |err| {
    std.debug.print("Erro: {}\n", .{err});
}

// Com tipo de erro específico
if (resultado) |valor| {
    processar(valor);
} else |err| switch (err) {
    error.OutOfMemory => @panic("Sem memória"),
    error.InvalidInput => std.log.warn("Entrada inválida\n", .{}),
    else => return err,
}
```

## defer e errdefer

```zig
fn abrirConexao() !Conexao {
    const socket = try criarSocket();
    // errdefer SÓ executa se a função retornar erro
    errdefer socket.close();

    try socket.connect(endereco);
    // Se connect falhar, socket.close() é chamado

    const sessao = try iniciarSessao(socket);
    errdefer sessao.fechar();

    try autenticar(sessao);
    // Se autenticar falhar, sessao.fechar() e socket.close() são chamados

    return .{ .socket = socket, .sessao = sessao };
    // Se tudo der certo, errdefers NÃO executam
}

// defer sempre executa ao sair do escopo
fn processarArquivo(path: []const u8) !void {
    const file = try std.fs.cwd().openFile(path, .{});
    defer file.close();  // SEMPRE fecha, erro ou não

    const allocator = std.heap.page_allocator;
    const data = try file.readToEndAlloc(allocator, 1024 * 1024);
    defer allocator.free(data);  // SEMPRE libera

    try processar(data);
}

// Ordem de execução: LIFO (último a entrar, primeiro a sair)
fn exemplo() void {
    defer std.debug.print("1\n", .{});
    defer std.debug.print("2\n", .{});
    defer std.debug.print("3\n", .{});
    // Imprime: 3, 2, 1
}
```

## Erros em Loops

```zig
// Coletar resultados, ignorando erros
fn processarTodos(items: []const Item) void {
    for (items) |item| {
        processar(item) catch |err| {
            std.log.warn("Falha no item: {}\n", .{err});
            continue;
        };
    }
}

// Parar no primeiro erro
fn processarTodosOuFalhar(items: []const Item) !void {
    for (items) |item| {
        try processar(item);
    }
}
```

## Padrão Retry

```zig
fn comRetry(comptime max_tentativas: u32, func: anytype, args: anytype) !ReturnType(@TypeOf(func)) {
    var tentativa: u32 = 0;
    while (tentativa < max_tentativas) : (tentativa += 1) {
        if (@call(.auto, func, args)) |resultado| {
            return resultado;
        } else |err| {
            if (tentativa == max_tentativas - 1) return err;
            std.time.sleep(std.time.ns_per_s * std.math.pow(u64, 2, tentativa));
        }
    }
    unreachable;
}
```

## Erros Customizados com Contexto

```zig
const ParseError = struct {
    linha: usize,
    coluna: usize,
    mensagem: []const u8,
};

const Parser = struct {
    ultimo_erro: ?ParseError = null,

    pub fn parse(self: *Parser, input: []const u8) error{ParseFailed}!AST {
        // ... lógica de parse
        if (encontrou_erro) {
            self.ultimo_erro = .{
                .linha = linha_atual,
                .coluna = coluna_atual,
                .mensagem = "Token inesperado",
            };
            return error.ParseFailed;
        }
        // ...
    }
};

// Uso
var parser = Parser{};
const ast = parser.parse(codigo) catch {
    if (parser.ultimo_erro) |err| {
        std.log.err("Erro na linha {}, coluna {}: {s}\n", .{
            err.linha, err.coluna, err.mensagem,
        });
    }
    return;
};
_ = ast;
```

## Erros em Funções de Teste

```zig
test "operação deve suceder" {
    const resultado = try operacao();
    try std.testing.expectEqual(@as(i32, 42), resultado);
}

test "operação deve falhar" {
    const resultado = operacao();
    try std.testing.expectError(error.InvalidInput, resultado);
}

test "com expectEqual de erros" {
    if (operacao()) |_| {
        return error.TestUnexpectedResult;
    } else |err| {
        try std.testing.expectEqual(error.NotFound, err);
    }
}
```

## Tabela de Referência

| Operação | Sintaxe | Descrição |
|----------|---------|-----------|
| Definir erros | `error{ A, B }` | Conjunto de erros |
| Error union | `E!T` ou `!T` | Tipo que pode ser erro |
| Retornar erro | `return error.Nome` | Produzir erro |
| Propagar | `try expr` | Propagar erro se houver |
| Valor padrão | `expr catch val` | Valor se erro |
| Tratar | `expr catch \|e\| ...` | Bloco de tratamento |
| Cleanup sempre | `defer expr` | Executa ao sair do escopo |
| Cleanup no erro | `errdefer expr` | Executa só se erro |
| Assert sem erro | `expr catch unreachable` | Panic se erro |
| Desempacotar | `if (expr) \|v\| ... else \|e\| ...` | Condição com erro |

Se você já trabalha com tratamento de erros em outras linguagens de sistemas, vale comparar as abordagens: <a href="https://golang.com.br/artigos/go-error-handling/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go utiliza múltiplos retornos (value, error)</a> de forma semelhante ao error union de Zig, enquanto <a href="https://rustlang.com.br/artigos/rust-error-handling/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust adota o tipo Result&lt;T, E&gt;</a> com pattern matching obrigatório.

## Veja Também

- [Controle de Fluxo](/cheatsheets/controle-fluxo/) — if, switch com erros
- [Funções](/cheatsheets/funcoes/) — Retorno de erros em funções
- [Testing](/cheatsheets/testing/) — Testes com erros
- [Padrão Retry](/padroes/retry-pattern/) — Padrão de retentativa
- [Padrão Circuit Breaker](/padroes/circuit-breaker/) — Proteção contra falhas
- [Troubleshooting: Crashes](/troubleshooting/zig-crash-runtime/) — Debug de erros em runtime
