crowdsecurity/crowdsec · error

failed to parse JSON line in %s: %w

Error message

failed to parse JSON line in %s: %w

What it means

fileMapInit parses each line of a JSON-lines 'map' data file into a map[string]string. This error is thrown when the line is not valid JSON — json.Unmarshal fails with a syntax or type error that is wrapped as %w. Unlike botFileInit, unknown extra fields are allowed here (target is a generic map), so this fires purely on malformed JSON or non-string JSON values.

Source

Thrown at pkg/exprhelpers/filemap.go:47

type matchIndex struct {
	// O(1) map for "equals" entries (checked first).
	equalsMap map[string]int // exact pattern value → row index

	// Aho-Corasick automaton for "contains" entries (O(|haystack|) matching, checked second).
	acAutomaton    *aho_corasick.AhoCorasick
	acPatternToRow []int // AC pattern index → row index in fileMapEntry.rows

	// Pre-compiled regexps for "regex" entries (checked last).
	regexPatterns []*regexp.Regexp
	regexToRow    []int // regex slice index → row index in fileMapEntry.rows
}

// fileMapInit parses a single JSON line and appends it to the fileMapEntry for the given filename.
// Three fields are mandatory: "pattern", "tag", and "type" (one of: "equals", "contains", "regex").
func fileMapInit(filename string, line string) error {
	var record map[string]string
	if err := json.Unmarshal([]byte(line), &record); err != nil {
		return fmt.Errorf("failed to parse JSON line in %s: %w", filename, err)
	}

	if record["pattern"] == "" {
		return fmt.Errorf("missing mandatory 'pattern' field in %s: %s", filename, line)
	}

	if record["tag"] == "" {
		return fmt.Errorf("missing mandatory 'tag' field in %s: %s", filename, line)
	}

	entryType := record["type"]
	if entryType == "" {
		return fmt.Errorf("missing mandatory 'type' field in %s: %s", filename, line)
	}

	if !slices.Contains(validMapEntryTypes, entryType) {
		return fmt.Errorf("unknown entry type '%s' in %s (supported: %s): %s",
			entryType, filename, strings.Join(validMapEntryTypes, ", "), line)

View on GitHub (pinned to 909b515798)

Solutions

  1. Run `echo '<line>' | jq .` — the wrapped %w error names the exact syntax problem; fix that character.
  2. Ensure every value (pattern, tag, type, extras) is a JSON string: quote numbers/booleans ("tag":"123").
  3. Ensure the file is one JSON object per line (JSONL): no array wrappers, no inter-line commas, no BOM.
  4. Re-encode the file as UTF-8 without BOM (`dos2unix`, editor save-as UTF-8).
  5. Re-export the source data with a proper JSONL writer (e.g. jq -c) if a conversion step produced it.

Example fix

// before
{"pattern":"foo","tag":123,}
// after
{"pattern":"foo","tag":"123"}
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate a map file line: must be a JSON object with all-string values
var raw map[string]json.RawMessage
if err := json.Unmarshal([]byte(line), &raw); err != nil {
	return false
}
for _, v := range raw {
	if !strings.HasPrefix(string(v), "\"") {
		return false // non-string value
	}
}
return raw["pattern"] != nil && raw["tag"] != nil && raw["type"] != nil

Try / catch

if err := exprhelpers.FileInit(mapFile, "map"); err != nil {
	if strings.Contains(err.Error(), "failed to parse JSON line") {
		log.Errorf("malformed map entry: %v", err)
	}
	return err
}

Prevention

When it happens

Trigger: A line in a map data file is not a JSON object of strings: broken syntax (unterminated string, trailing comma), a bare value like `true`, a JSON array, or nested objects/numbers for fields, e.g. {"pattern":"a","tag":123}.

Common situations: Hand-edited lookup files with typos; exporting from CSV/spreadsheet producing invalid JSONL; a field accidentally numeric or boolean instead of a string; file truncated mid-line by a failed transfer; UTF-16/BOM encoding from Windows editors.

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 crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/e7139a88647c3649. Report an issue: GitHub.