owasp-amass/amass · error

failed to unmarshal the level text

Error message

failed to unmarshal the level text

What it means

The level value was a string, but slog.Level.UnmarshalText could not parse it into a valid slog.Level; this error is returned instead of propagating the parse failure detail. Only recognized level names (DEBUG, INFO, WARN, ERROR and their variants) are accepted.

Source

Thrown at internal/afmt/slog.go:40

	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)
	record.AddAttrs(jsonToAttrs(j)...)
	return record, nil

View on GitHub (pinned to 79299dce87)

Solutions

  1. Use standard slog level names (DEBUG, INFO, WARN/WARNING, ERROR) in the producer's JSON output
  2. Map custom producer levels to slog levels before calling JSONLogToRecord
  3. Align producer and consumer library versions so supported level sets match
  4. Check for stray whitespace or casing issues; normalize the level string before parsing

Example fix

// before
{"time":"...","level":"verbose","msg":"started"}
// after
{"time":"...","level":"DEBUG","msg":"started"}
Defensive patterns

Strategy: validation

Validate before calling

var validLevels = map[string]bool{"DEBUG":true,"INFO":true,"WARN":true,"WARNING":true,"ERROR":true}
if v, ok := j[slog.LevelKey].(string); ok && !validLevels[v] {
    return fmt.Errorf("unknown log level %q", v)
}

Try / catch

rec, err := afmt.JSONLogToRecord(line)
if err != nil {
    if strings.Contains(err.Error(), "failed to unmarshal the level text") {
        rawLog.Printf("unparseable level in log line: %q", line)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: JSONLogToRecord receives a log line with a string "level" whose text is not a valid slog level — e.g. "verbose", "TRACE", "warning" (lowercase works for some parsers but arbitrary aliases do not), or an empty string.

Common situations: Custom level names from a producer using its own level enum; case/format drift between producer and consumer; an engine version that introduced levels the consumer's slog version does not know.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06). Data as JSON: /api/errors/eccb8c8f67bb19f6. Report an issue: GitHub.