Strukturierte Fehlerobjekte
Übergeben Sie Tabellen als Fehlerobjekte, um Typ und Kontext zu übermitteln
Strukturierte Fehlerobjekte ist eine kostenlose Lua Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Lua Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum strukturierte Fehler?
Einfache String-Fehler lassen sich nur schwer programmgesteuert behandeln. Strukturierte Fehlerobjekte (Tabellen) enthalten Typinformationen und Kontextdaten und können von Aufrufern untersucht und verarbeitet werden. Dadurch wird eine fehlerbasierte Weiterleitung ohne Parsen von Zeichenketten möglich.
-- Plain string: hard to handle programmatically
error("database error: connection refused")
-- Structured: type + data
error({
type = "DatabaseError",
code = "CONN_REFUSED",
host = "localhost",
port = 5432,
message = "connection refused"
})Muster für Fehlerkonstruktoren
Erstellen Sie für jeden Fehlertyp eine Fehlerfabrikfunktion. Die Fabrik erstellt eine Tabelle mit konsistenten Feldern: Typ, Nachricht und alle relevanten Kontextinformationen. Eine __tostring-Metamethode sorgt für eine übersichtliche Ausgabe des Fehlers.
local ErrorMT = {__tostring = function(e)
return string.format("[%s] %s", e.type, e.message)
end}
local function makeError(errType, msg, data)
local e = {type=errType, message=msg}
if data then for k,v in pairs(data) do e[k]=v end end
return setmetatable(e, ErrorMT)
end
local E = {
notFound = function(name) return makeError("NOT_FOUND","not found: "..name,{name=name}) end,
badInput = function(msg,field) return makeError("BAD_INPUT",msg,{field=field}) end,
}
local ok, err = pcall(error, E.notFound("user:42"))
print(tostring(err)) -- [NOT_FOUND] not found: user:42Fehlerobjekte auf ihren Typ prüfen
Prüfen Sie nach dem Abfangen eines Fehlers, ob es sich um eine Tabelle mit einem bekannten Typfeld handelt. So können Sie je nach Fehlertyp unterschiedliche Wiederherstellungsstrategien auswählen, ohne auf Zeichenkettenmuster angewiesen zu sein.
local function handleRequest(fn)
local ok, err = pcall(fn)
if ok then return true end
if type(err) == "table" then
if err.type == "NOT_FOUND" then
print("404: " .. err.message)
elseif err.type == "BAD_INPUT" then
print("400: " .. err.message .. " (field: " .. (err.field or "?") .. ")")
else
print("500: unhandled error: " .. tostring(err))
end
else
print("500: " .. tostring(err))
end
return false
endFehlerhierarchie
Simulieren Sie eine Fehlerhierarchie, indem Sie is_a-Felder prüfen oder Metatabellen verwenden. Untergeordnete Fehlertypen erben die Felder des übergeordneten Typs und können von Code, der keine Details benötigt, wie der übergeordnete Typ behandelt werden.
local function isError(e, errType)
if type(e) ~= "table" then return false end
return e.type == errType or e.parentType == errType
end
local function makeDbError(code, msg)
return {type="DbError:"..code, parentType="DbError", code=code, message=msg}
end
local err = makeDbError("TIMEOUT","query timed out")
print(isError(err, "DbError")) -- true
print(isError(err, "DbError:TIMEOUT")) -- true
print(isError(err, "NetworkError")) -- falseFehler verpacken
Wenn Sie einen Fehler abfangen und erneut auslösen, verpacken Sie den ursprünglichen Fehler, um Kontext hinzuzufügen, ohne ihn zu verlieren. Der Wrapper hat einen eigenen Typ und enthält den ursprünglichen Fehler als Ursache.
local function wrapError(msg, cause)
return {
type = "WrappedError",
message = msg,
cause = cause,
}
end
local function loadConfig(path)
local ok, err = pcall(function()
local f = assert(io.open(path,"r"))
local content = f:read("a")
f:close()
return content
end)
if not ok then
error(wrapError("failed to load config: "..path, err))
end
end
local ok2, e = pcall(loadConfig, "missing.cfg")
if not ok2 then
print(e.message)
print("Caused by:", tostring(e.cause))
endFehlercodes im Vergleich zu Fehlertypen
Zwei verbreitete Konventionen sind Fehlercodes (numerisch, etwa wie HTTP-Statuscodes) und Fehlertexten (semantische Bezeichnungen). Fehlercodes lassen sich leicht numerisch vergleichen, Typtexte sind selbsterklärend. Viele Systeme verwenden beides.
local STATUS = {OK=200, NOT_FOUND=404, SERVER_ERROR=500, BAD_REQUEST=400}
local function makeStatusError(status, msg)
return {status=status, message=msg, type="HTTPError"}
end
local function handleError(e)
if e.status == STATUS.NOT_FOUND then
print("Resource not found:", e.message)
elseif e.status >= 500 then
print("Server error:", e.message)
else
print("Error", e.status, e.message)
end
end
handleError(makeStatusError(404, "user not found"))Fehlerstapel (Ursachenkette)
Wenn ein Fehler durch einen anderen verursacht wurde, verknüpfen Sie sie. So erhalten Sie ein vollständiges Bild davon, was auf den einzelnen Ebenen der Anwendung schiefgelaufen ist. Entpacken Sie die Kette, um die vollständige Fehlerursache zu protokollieren oder anzuzeigen.
local function unwindCause(e, depth)
depth = depth or 0
local pad = string.rep(" ", depth)
if type(e) == "table" then
print(pad .. (e.type or "Error") .. ": " .. (e.message or "?"))
if e.cause then unwindCause(e.cause, depth+1) end
else
print(pad .. tostring(e))
end
end
local inner = {type="IoError", message="permission denied"}
local outer = {type="ConfigError", message="cannot load config", cause=inner}
unwindCause(outer)
-- ConfigError: cannot load config
-- IoError: permission deniedFehler im Callback-Kontext
Wenn innerhalb von Callbacks (Ereignishandlern, Iteratoren) Fehler auftreten, werden sie an den Aufrufer des Callbacks weitergegeben. Verwenden Sie pcall, um sie abzufangen und mit dem Kontext zu melden, welcher Callback fehlgeschlagen ist.
local function runCallbacks(callbacks, data)
local errors = {}
for name, fn in pairs(callbacks) do
local ok, err = pcall(fn, data)
if not ok then
errors[#errors+1] = {callback=name, error=err}
end
end
return errors
end
local cbs = {
validate = function(d) assert(d.name, "name required") end,
transform = function(d) d.name = d.name:upper() end,
}
local errs = runCallbacks(cbs, {})
for _, e in ipairs(errs) do
print(e.callback, "->", e.error)
endFehlerdetails ausgeben
Eine Hilfsfunktion, die ein Fehlerobjekt strukturiert und verständlich ausgibt und dabei sowohl String- als auch Tabellenfehler behandelt. Das ist an Anwendungsgrenzen nützlich, an denen Fehler protokolliert oder Benutzern angezeigt werden.
local function printError(err, prefix)
prefix = prefix or "Error"
if type(err) ~= "table" then
print(prefix .. ": " .. tostring(err))
return
end
print(prefix .. " [" .. (err.type or "unknown") .. "]")
print(" Message: " .. (err.message or "?"))
for k, v in pairs(err) do
if k ~= "type" and k ~= "message" and k ~= "cause" then
print(" " .. k .. ": " .. tostring(v))
end
end
if err.cause then printError(err.cause, " Caused by") end
endMit strukturierten Fehlern Zusicherungen prüfen
Erstellen Sie ein assertT (assert mit typisierten Fehlern), das einen strukturierten Fehler anstelle eines einfachen Strings auslöst. Dadurch können Aufrufer leicht auf bestimmte Fehlertypen testen.
local function assertT(cond, errType, msg, data)
if not cond then
local e = {type=errType, message=msg}
if data then for k,v in pairs(data) do e[k]=v end end
error(e, 2)
end
return cond
end
local function createUser(name, age)
assertT(type(name)=="string", "BAD_INPUT", "name must be string", {field="name"})
assertT(age >= 0 and age <= 150, "BAD_INPUT", "invalid age", {field="age", value=age})
return {name=name, age=age}
end
local ok, err = pcall(createUser, "Alice", -5)
if not ok then print(err.type, err.field, err.value) endSchnelltest
Was ist der wichtigste Vorteil, wenn Sie eine Tabelle statt eines Strings an error() übergeben?
Zusammenfassung: Strukturierte Fehler
Zusammenfassung:
- Übergeben Sie Tabellen an
error(), um strukturierte und untersuchbare Fehler zu erhalten - Fügen Sie Typ, Nachricht und relevante Kontextfelder hinzu
- Fügen Sie
__tostringfür eine verständliche Ausgabe hinzu - Verpacken Sie Fehler, um Kontext hinzuzufügen, ohne die Ursache zu verlieren
- Leiten Sie in Handlern anhand des Typs weiter: Prüfen Sie
err.typestatt Zeichenkettenmuster
Häufig gestellte Fragen
Ist die Lektion „Strukturierte Fehlerobjekte“ kostenlos?
Ja — der vollständige Text von „Strukturierte Fehlerobjekte“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Lua Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Strukturierte Fehlerobjekte“?
Übergeben Sie Tabellen als Fehlerobjekte, um Typ und Kontext zu übermitteln Du übst Lua Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Lua Academy zu starten?
Keine Vorkenntnisse erforderlich. Lua Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Strukturierte Fehlerobjekte“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Lua Academy-Lektion Code schreiben und ausführen?
Ja. Jede Lua Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Die Funktion error()
- Geschützte Aufrufe mit pcall
- xpcall und Nachrichten-Handler
- Strukturierte Fehlerobjekte