crowdsecurity/crowdsec · error

key %s does not exist

Error message

key %s does not exist

What it means

jsonExtractType (backing JsonExtractSlice/JsonExtractObject) walks a dotted path through a JSON blob with jsonparser. When the requested key path does not exist in the document, jsonparser returns KeyPathNotFoundError and this function surfaces it as 'key <path> does not exist'. Unlike JsonExtract, these typed extractors propagate the error instead of returning an empty result.

Source

Thrown at pkg/exprhelpers/jsonextract.go:98

	return JsonExtractLib(jsblob, fullpath)
}

func jsonExtractType(jsblob string, target string, t jsonparser.ValueType) ([]byte, error) {
	if !strings.HasPrefix(target, "[") {
		target = strings.ReplaceAll(target, "[", ".[")
	}
	fullpath := strings.Split(target, ".")

	log.Tracef("extract path %+v", fullpath)

	value, dataType, _, err := jsonparser.Get(
		jsonparser.StringToBytes(jsblob),
		fullpath...,
	)
	if err != nil {
		if errors.Is(err, jsonparser.KeyPathNotFoundError) {
			log.Debugf("Key %+v doesn't exist", target)
			return nil, fmt.Errorf("key %s does not exist", target)
		}
		log.Errorf("jsonExtractType : %s : %s", target, err)
		return nil, fmt.Errorf("jsonExtractType: %s : %w", target, err)
	}

	if dataType != t {
		log.Errorf("jsonExtractType : expected type %s for target %s but found %s", t, target, dataType.String())
		return nil, fmt.Errorf("jsonExtractType: expected type %s for target %s but found %s", t, target, dataType.String())
	}

	return value, nil
}

// func JsonExtractSlice(jsblob string, target string) []interface{} {
func JsonExtractSlice(params ...any) (any, error) {
	jsblob := params[0].(string)
	target := params[1].(string)

View on GitHub (pinned to 909b515798)

Solutions

  1. Verify the exact key path in the actual JSON payload, matching case and nesting
  2. Check the key exists (JsonExtract returns "" for missing keys and can be used as a probe) before calling the typed extractors
  3. Handle the error and fall back to an empty slice/object in the caller
  4. Add an upstream schema check or log the raw blob when the key is expected but missing

Example fix

// before: assumes key always exists
val, err := JsonExtractSlice(evt, "attack_details.targets")
// after: probe with tolerant extractor or guard
if JsonExtract(evt, "attack_details.targets") == "" {
    return []interface{}{}, nil
}
val, err := JsonExtractSlice(evt, "attack_details.targets")
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(target, "[") == false && !json.Valid([]byte(jsblob)) {
    return errors.New("blob is not valid JSON")
}
probe := exprhelpers.JsonExtract(jsblob, target)
if probe == "" { return errors.New("key missing: " + target) }

Try / catch

val, err := exprhelpers.JsonExtractSlice(jsblob, target)
if err != nil {
    log.Debugf("key %s missing: %v", target, err)
    return []interface{}{}, nil // tolerate missing keys
}

Prevention

When it happens

Trigger: Calling JsonExtractSlice(jsblob, target) or JsonExtractObject(jsblob, target) where target (dotted path, [i] for array indices) names a key missing from jsblob — typo, wrong nesting level, key absent in that particular event.

Common situations: Parsing heterogeneous log/agent payloads where the field is optional; renaming of upstream JSON fields; wrong case ('Request' vs 'request'); indexing past the end of an array.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/9ff3f9e9e2ef539e. Report an issue: GitHub.