owasp-amass/amass · error

failed to unmarchal the JSON

Error message

failed to unmarchal the JSON

What it means

JSONLogToRecord converts a JSON-formatted log line emitted by the engine session into a slog.Record. If json.Unmarshal fails on the input string, the function cannot proceed and returns this generic error (note the typo 'unmarchal' in the message). It throws because a non-JSON or truncated line cannot be mapped to a structured record.

Source

Thrown at internal/afmt/slog.go:20

// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// SPDX-License-Identifier: Apache-2.0

package afmt

import (
	"encoding/json"
	"errors"
	"fmt"
	"log/slog"
	"strconv"
	"time"
)

func JSONLogToRecord(logstr string) (slog.Record, error) {
	j := make(map[string]any)
	// 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")

View on GitHub (pinned to 79299dce87)

Solutions

  1. Ensure the engine session writes one complete JSON object per line (JSON Lines format)
  2. Validate the input with json.Valid([]byte(logstr)) before calling JSONLogToRecord and log raw lines that fail
  3. Check for truncation — read full lines with a scanner and proper buffer size
  4. Confirm the engine and the log consumer use the same serialization options (no HTML escaping or custom field differences that break parsing)

Example fix

// before
if err := json.Unmarshal([]byte(logstr), &j); err != nil {
    return slog.Record{}, errors.New("failed to unmarchal the JSON")
}
// after
if !json.Valid([]byte(logstr)) {
    return slog.Record{}, fmt.Errorf("failed to unmarshal the JSON: %q", logstr)
}
if err := json.Unmarshal([]byte(logstr), &j); err != nil {
    return slog.Record{}, fmt.Errorf("failed to unmarshal the JSON: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid([]byte(logstr)) {
    // route to raw-log sink instead of JSONLogToRecord
    return errors.New("not a JSON log line")
}

Try / catch

rec, err := afmt.JSONLogToRecord(line)
if err != nil {
    if strings.Contains(err.Error(), "unmarchal the JSON") {
        rawLog.Printf("non-JSON log line dropped: %q", line)
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: WriteLogMessage receives a logstr that is not valid JSON: empty string, plain-text log line, partially written/truncated line from a broken pipe, or a line with a JSON-unrepresentable payload.

Common situations: Mixing human-readable and JSON log formats in the same stream; reading a line before the writer finished flushing; engine emitting a stack trace or multi-line message; encoding bugs upstream.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — 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/ae6d28e4a1cca3a0. Report an issue: GitHub.