xpcall e manipuladores de mensagens
Use xpcall com um manipulador personalizado para obter rastreamentos detalhados de erros.
xpcall e manipuladores de mensagens é uma aula grátis de Lua Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Lua Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Lua Academy inclui 4 aulas no total.
Sintaxe de xpcall
xpcall(f, handler, ...) chama f com os argumentos ... em modo protegido e, em caso de erro, chama handler(errorObject). O valor retornado pelo manipulador torna-se o segundo valor retornado por xpcall. Diferentemente de pcall, xpcall executa o manipulador enquanto a pilha está intacta.
local function handler(err)
return "HANDLED: " .. tostring(err)
end
local ok, msg = xpcall(
function() error("something bad") end,
handler
)
print(ok) -- false
print(msg) -- HANDLED: ...: something baddebug.traceback como manipulador
O manipulador de xpcall mais comum é debug.traceback. Passe-o diretamente como manipulador — ele formata o erro com um rastreamento completo da pilha de chamadas, algo indispensável para depurar erros em produção.
local function level3() error("deep error") end
local function level2() level3() end
local function level1() level2() end
local ok, err = xpcall(level1, debug.traceback)
if not ok then
-- err contains the full stack trace
print(err)
endManipulador personalizado com contexto
Um manipulador personalizado pode adicionar contexto: registrar o horário, gravar em um arquivo, notificar sistemas de monitoramento e então retornar o erro formatado. Esse é o padrão comum para o tratamento de erros em produção em aplicações Lua.
local function errorHandler(err)
local trace = debug.traceback(err, 2)
local ts = os.date("%H:%M:%S")
local report = string.format("[%s] ERROR\n%s", ts, trace)
-- Could log to file here
io.stderr:write(report .. "\n")
return report
end
local ok, msg = xpcall(
function()
local t = nil
return t.field -- error!
end,
errorHandler
)
print("ok:", ok)O manipulador não pode gerar erros
Se o próprio manipulador de mensagens gerar um erro, Lua retornará um indicador de erro sem chamar o manipulador novamente. Escreva sempre manipuladores à prova de falhas — sem E/S que possa falhar e sem indexação de valores nil.
local function safeHandler(err)
-- Keep handler simple and safe
local ok, trace = pcall(debug.traceback, err, 2)
if ok then return trace
else return tostring(err) .. " (traceback failed)"
end
end
local ok, msg = xpcall(
function() error({complex="error table"}) end,
safeHandler
)
print(ok, type(msg))xpcall para o laço principal
Em programas de longa duração (servidores, laços de jogos), envolva a função principal em xpcall para capturar e registrar quaisquer erros não tratados sem causar uma falha. O laço principal poderá então decidir se deve reiniciar ou sair.
local function mainApp()
-- simulate work
for i = 1, 3 do
print("Tick", i)
if i == 2 then error("transient error") end
end
end
local function handler(e)
return debug.traceback("App error: "..tostring(e), 2)
end
local ok, err = xpcall(mainApp, handler)
if not ok then
print("Application crashed:\n" .. err)
endRelatórios de erros estruturados
Combine xpcall com objetos de erro estruturados e um manipulador avançado para produzir relatórios de erro detalhados e acionáveis para depuração ou painéis de monitoramento.
local function handler(err)
local info = {
error = tostring(err),
time = os.date("!%Y-%m-%dT%H:%M:%SZ"),
trace = debug.traceback(nil, 2),
}
return info
end
local ok, report = xpcall(
function() error({code=500, msg="internal error"}) end,
handler
)
if not ok then
print("Time:", report.time)
print("Error:", report.error)
-- print("Trace:", report.trace)
endxpcall para corrotinas
Dentro de uma corrotina, pcall funciona normalmente. Para obter rastreamentos de erros dentro de corrotinas, envolva o corpo da corrotina em xpcall. O manipulador é executado dentro do contexto da pilha da corrotina.
local function co_body()
error("error inside coroutine")
end
local co = coroutine.create(function()
local ok, err = xpcall(co_body, debug.traceback)
if not ok then
print("Caught in coroutine:", err:match("([^\n]+)"))
end
end)
coroutine.resume(co)Enriquecimento de objetos de erro
O manipulador pode transformar um erro simples em string em um objeto avançado, ou enriquecer ainda mais um objeto avançado. Isso permite que o código de baixo nível gere erros simples enquanto o manipulador adiciona contexto (ID da solicitação, sessão do usuário e informações do ambiente).
local requestID = "req-123"
local function handler(err)
if type(err) == "string" then
return {message=err, requestID=requestID, level="error"}
end
err.requestID = requestID
return err
end
local ok, result = xpcall(
function() error("database timeout") end,
handler
)
if not ok then
print(result.message, result.requestID)
-- database timeout req-123
endComparação entre pcall e xpcall
Use pcall quando: você precisar apenas do valor do erro, o erro for esperado e tratado no próprio local, ou a simplicidade for importante. Use xpcall quando: precisar de rastreamentos da pilha, estiver em um limite de nível superior ou quiser adicionar contexto a todos os erros.
-- pcall: simple, no overhead
local ok, err = pcall(function()
return 1/0 -- no error in Lua! returns inf
end)
print(ok, err) -- true inf
-- xpcall: adds traceback
local ok2, err2 = xpcall(
function() error("real error") end,
debug.traceback
)
print(ok2) -- false
print(err2:sub(1,40)) -- first line of tracebackValor retornado pelo manipulador
Qualquer valor retornado pelo manipulador torna-se o segundo valor de xpcall. Se o manipulador retornar nil, o segundo retorno de xpcall será nil. Um manipulador que retorna o objeto de erro original junto com informações adicionais é a abordagem mais flexível.
local function enrichedHandler(err)
return {
original = err,
traceback = debug.traceback(nil, 2),
timestamp = os.time(),
}
end
local ok, report = xpcall(
function() error("oops") end,
enrichedHandler
)
if not ok then
print(type(report)) -- table
print(report.original) -- ...: oops
print(report.timestamp > 0) -- true
endVerificação rápida
Qual é a principal vantagem de xpcall em relação a pcall?
Recapitulação: xpcall
Resumo:
xpcall(f, handler, ...)— o manipulador é executado enquanto a pilha está intacta- Use
debug.tracebackcomo manipulador para obter rastreamentos completos - O manipulador não pode gerar erros — mantenha-o simples
- Enriqueça os erros com contexto no manipulador
- Envolva os laços principais e os manipuladores de servidor em xpcall
- O retorno do manipulador torna-se o segundo valor retornado por xpcall
Perguntas Frequentes
A aula “xpcall e manipuladores de mensagens” é grátis?
Sim — o texto completo de “xpcall e manipuladores de mensagens” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Lua Academy, atualize para CoddyKit PRO. O curso de Lua Academy inclui 4 aulas no total.
O que vou aprender em “xpcall e manipuladores de mensagens”?
Use xpcall com um manipulador personalizado para obter rastreamentos detalhados de erros. Você pratica Lua Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Lua Academy?
Nenhuma experiência prévia é necessária. Lua Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “xpcall e manipuladores de mensagens”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Lua Academy?
Sim. Cada aula de Lua Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- A função error()
- Chamadas protegidas com pcall
- xpcall e manipuladores de mensagens
- Objetos de erro estruturados