crowdsecurity/crowdsec · error

jsonExtractType: expected type %s for target %s but found %s

Error message

jsonExtractType: expected type %s for target %s but found %s

What it means

jsonExtractType enforces the expected jsonparser.ValueType: JsonExtractSlice requires Array and JsonExtractObject requires Object. If the key path exists but holds a different type (string, number, null...), extraction fails with this message naming expected vs actual type.

Source

Thrown at pkg/exprhelpers/jsonextract.go:106

	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)

	value, err := jsonExtractType(jsblob, target, jsonparser.Array)
	if err != nil {
		log.Errorf("JsonExtractSlice : %s", err)
		return []interface{}(nil), nil
	}

	s := make([]interface{}, 0)

View on GitHub (pinned to 909b515798)

Solutions

  1. Confirm the actual type at that path in a sample payload and use the matching extractor (JsonExtractSlice vs JsonExtractObject)
  2. Treat null/absent-type cases explicitly before extraction (null dataType is a common mismatch)
  3. Add schema validation upstream so type changes are caught early
  4. Handle the error and return an empty slice/object instead of failing the expression

Example fix

// before: expects array but field may be object
vals, err := JsonExtractSlice(evt, "items")
// after: fall back on type error
vals, err := JsonExtractSlice(evt, "items")
if err != nil {
    obj, oerr := JsonExtractObject(evt, "items")
    if oerr != nil { return []interface{}{}, nil }
    vals = []interface{}{obj}
}
Defensive patterns

Strategy: fallback

Validate before calling

// no cheap pre-check via public API; validate shape with encoding/json
var probe any
if err := json.Unmarshal([]byte(jsblob), &probe); err == nil {
    if v, ok := dig(probe, target); ok {
        if _, isArr := v.([]any); !isArr {
            return errors.New("target is not an array")
        }
    }
}

Try / catch

vals, err := exprhelpers.JsonExtractSlice(jsblob, target)
if err != nil && strings.Contains(err.Error(), "but found") {
    // type drift: fall back to tolerant extraction
    return []interface{}{}, nil
}

Prevention

When it happens

Trigger: Calling JsonExtractSlice on a key that holds a string or object, or JsonExtractObject on a key holding an array/scalar/null; upstream field type changed between payload versions.

Common situations: API/schema drift where 'targets' becomes a string or 'details' becomes null; indexing a JSON field that is sometimes an array and sometimes a single object.

Related errors


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