{"record":{"id":"a5d5332a16b12f32","repo":"owasp-amass/amass","slug":"failed-to-find-the-level-key","errorCode":null,"errorMessage":"failed to find the level key","messagePattern":"failed to find the level key","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/afmt/slog.go","lineNumber":36,"sourceCode":"\t// unmarshal the log message sent from the engine session\n\tif err := json.Unmarshal([]byte(logstr), &j); err != nil {\n\t\treturn slog.Record{}, errors.New(\"failed to unmarchal the JSON\")\n\t}\n\n\tltime := time.Now()\n\tif timeVal, found := j[slog.TimeKey]; found {\n\t\tif timestr, valid := timeVal.(string); valid {\n\t\t\tif t, err := time.Parse(\"2006-01-02T15:04:05.000000000Z\", timestr); err == nil {\n\t\t\t\tltime = t\n\t\t\t}\n\t\t}\n\t}\n\tdelete(j, slog.TimeKey)\n\n\tvar level slog.Level\n\t// extract the log level for the new record\n\tif val, found := j[slog.LevelKey]; !found {\n\t\treturn slog.Record{}, errors.New(\"failed to find the level key\")\n\t} else if str, ok := val.(string); !ok {\n\t\treturn slog.Record{}, errors.New(\"failed to cast the level value\")\n\t} else if level.UnmarshalText([]byte(str)) != nil {\n\t\treturn slog.Record{}, errors.New(\"failed to unmarshal the level text\")\n\t}\n\tdelete(j, slog.LevelKey)\n\n\tvar msg string\n\t// extract the log message for the new record\n\tif val, found := j[slog.MessageKey]; !found {\n\t\treturn slog.Record{}, errors.New(\"failed to find the msg key\")\n\t} else if str, ok := val.(string); !ok {\n\t\treturn slog.Record{}, errors.New(\"failed to cast the msg value\")\n\t} else {\n\t\tmsg = str\n\t}\n\tdelete(j, slog.MessageKey)\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/internal/afmt/slog.go#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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\""],"exampleFix":"// before\n{\"time\":\"2026-09-06T10:00:00.000000000Z\",\"msg\":\"started\"}\n// after\n{\"time\":\"2026-09-06T10:00:00.000000000Z\",\"level\":\"INFO\",\"msg\":\"started\"}","handlingStrategy":"validation","validationCode":"var probe map[string]any\nif err := json.Unmarshal([]byte(logstr), &probe); err != nil {\n    return err\n}\nif _, ok := probe[slog.LevelKey]; !ok {\n    return errors.New(\"log line missing 'level' key\")\n}","typeGuard":"func hasLevelKey(j map[string]any) bool {\n    _, ok := j[slog.LevelKey]\n    return ok\n}","tryCatchPattern":"rec, err := afmt.JSONLogToRecord(line)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to find the level key\") {\n        rawLog.Printf(\"log line without level dropped: %q\", line)\n        return nil\n    }\n    return err\n}","preventionTips":["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"],"tags":["logging","json","schema"],"backgroundTag":"missing-required-argument","analyzedSha":"79299dce87b0085db0f2f4ef3e9c52cccb49f514","analyzedAt":"2026-09-06T08:22:48.198Z","contentChangedAt":"2026-09-06T08:22:48.198Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}