owasp-amass/amass · error
failed to cast the level value
Error message
failed to cast the level value
What it means
When the "level" key is present in the parsed JSON but its value is not a JSON string (e.g. a number like 3 or null), the type assertion val.(string) fails and this error is returned. slog.Level.UnmarshalText expects textual level names (DEBUG, INFO, WARN, ERROR), so a non-string level cannot be converted.
Source
Thrown at internal/afmt/slog.go:38
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)
var pc uintptr
record := slog.NewRecord(ltime, level, msg, pc)View on GitHub (pinned to 79299dce87)
Solutions
- Produce log levels as strings ("DEBUG","INFO","WARN","ERROR") in the engine's JSON output
- If you control the producer, convert numeric levels to text before writing the line
- If you cannot change the producer, pre-process the JSON map and stringify numeric levels before calling JSONLogToRecord
- Check producer/consumer library versions for schema agreement
Example fix
// before
{"time":"...","level":3,"msg":"started"}
// after
{"time":"...","level":"INFO","msg":"started"} Defensive patterns
Strategy: type-guard
Validate before calling
if v, ok := j[slog.LevelKey]; ok {
if _, isStr := v.(string); !isStr {
return errors.New("level value must be a JSON string")
}
} Type guard
func levelIsString(j map[string]any) bool {
v, ok := j[slog.LevelKey]
if !ok {
return false
}
_, isStr := v.(string)
return isStr
} Try / catch
rec, err := afmt.JSONLogToRecord(line)
if err != nil {
if strings.Contains(err.Error(), "failed to cast the level value") {
rawLog.Printf("non-string level in log line: %q", line)
return nil
}
return err
} Prevention
- Serialize log levels as strings, never numeric codes
- Normalize producer output so level is always a quoted level name
- Add a schema check on the producer side before writing log lines
- Keep producer and consumer on schema-compatible versions
When it happens
Trigger: JSONLogToRecord receives a log line where j["level"] is an int, float, bool, null, or nested object instead of a string.
Common situations: A producer serializing numeric log levels (0-4) while the consumer expects text; hand-written or tool-generated log lines; a schema mismatch between two library versions.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- failed to unmarchal the JSON
- failed to find the level key
- failed to unmarshal the level text
- resolvers section is not a list
- target must be a FQDN or IPAddress
AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06).
Data as JSON: /api/errors/5f71f242eef13956.
Report an issue: GitHub.