owasp-amass/amass · error
failed to find the level key
Error message
failed to find the level key
What it means
After unmarshalling, JSONLogToRecord looks up slog.LevelKey ("level") in the parsed map; if the key is absent, no slog level can be assigned to the record and this error is returned. The library requires every engine log line to carry an explicit level field.
Source
Thrown at internal/afmt/slog.go:36
// unmarshal the log message sent from the engine session
if err := json.Unmarshal([]byte(logstr), &j); err != nil {
return slog.Record{}, errors.New("failed to unmarchal the JSON")
}
ltime := time.Now()
if timeVal, found := j[slog.TimeKey]; found {
if timestr, valid := timeVal.(string); valid {
if t, err := time.Parse("2006-01-02T15:04:05.000000000Z", timestr); err == nil {
ltime = t
}
}
}
delete(j, slog.TimeKey)
var level slog.Level
// extract the log level for the new record
if val, found := j[slog.LevelKey]; !found {
return slog.Record{}, errors.New("failed to find the level key")
} else if str, ok := val.(string); !ok {
return slog.Record{}, errors.New("failed to cast the level value")
} else if level.UnmarshalText([]byte(str)) != nil {
return slog.Record{}, errors.New("failed to unmarshal the level text")
}
delete(j, slog.LevelKey)
var msg string
// extract the log message for the new record
if val, found := j[slog.MessageKey]; !found {
return slog.Record{}, errors.New("failed to find the msg key")
} else if str, ok := val.(string); !ok {
return slog.Record{}, errors.New("failed to cast the msg value")
} else {
msg = str
}
delete(j, slog.MessageKey)
View on GitHub (pinned to 79299dce87)
Solutions
- Ensure every log line written by the engine includes a "level" field (e.g. via a slog handler that always adds it)
- Check engine and consumer versions match so log schemas agree
- Validate the required keys (time, level, msg) before calling JSONLogToRecord and route non-conforming lines elsewhere
- Inspect the offending line to confirm the key spelling is exactly "level"
Example fix
// before
{"time":"2026-09-06T10:00:00.000000000Z","msg":"started"}
// after
{"time":"2026-09-06T10:00:00.000000000Z","level":"INFO","msg":"started"} Defensive patterns
Strategy: validation
Validate before calling
var probe map[string]any
if err := json.Unmarshal([]byte(logstr), &probe); err != nil {
return err
}
if _, ok := probe[slog.LevelKey]; !ok {
return errors.New("log line missing 'level' key")
} Type guard
func hasLevelKey(j map[string]any) bool {
_, ok := j[slog.LevelKey]
return ok
} Try / catch
rec, err := afmt.JSONLogToRecord(line)
if err != nil {
if strings.Contains(err.Error(), "failed to find the level key") {
rawLog.Printf("log line without level dropped: %q", line)
return nil
}
return err
} Prevention
- Configure the engine's slog handler to always emit the level key
- Verify producer and consumer log schemas in an integration test
- Reject or redirect non-conforming lines at ingest time
- Pin engine and consumer versions so the schema cannot drift
When it happens
Trigger: JSONLogToRecord (via WriteLogMessage) receives a valid JSON object that lacks a "level" field — e.g. hand-crafted log lines, events from a different component that only set msg/time, or an older engine version that omitted the level.
Common situations: Forwarding logs from a component whose JSON schema differs; engine version downgrade/upgrade changing log schema; injecting custom events into the log stream without a level key.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- failed to unmarchal the JSON
- failed to cast the level value
- failed to unmarshal the level text
- logger handler is not enabled
- no log file specified
AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06).
Data as JSON: /api/errors/a5d5332a16b12f32.
Report an issue: GitHub.