crowdsecurity/crowdsec · error
invalid type for headers: %T
Error message
invalid type for headers: %T
What it means
HTTPRequest is an expr-lang helper taking (method, url, headers map[string]any, body string). The headers argument must be a map[string]any (typically an expr map literal); any other Go type — map[string]string, nil, or a non-map — is rejected with this error before any request is made.
Source
Thrown at pkg/exprhelpers/http.go:128
}
// HTTPRequest(method string, url string, headers map[string]any, body string) (*HTTPResponse, error)
func HTTPRequest(params ...any) (any, error) {
method, ok := params[0].(string)
if !ok {
return nil, fmt.Errorf("invalid type for method: %T", params[0])
}
uri, ok := params[1].(string)
if !ok {
return nil, fmt.Errorf("invalid type for url: %T", params[1])
}
// headers is map[string]any so that expr map literals (map[string]interface{})
// are accepted; values are stringified.
rawHeaders, ok := params[2].(map[string]any)
if !ok {
return nil, fmt.Errorf("invalid type for headers: %T", params[2])
}
headers := make(map[string]string, len(rawHeaders))
for k, v := range rawHeaders {
headers[k] = fmt.Sprint(v)
}
body, ok := params[3].(string)
if !ok {
return nil, fmt.Errorf("invalid type for body: %T", params[3])
}
var reader io.Reader
if body != "" {
reader = strings.NewReader(body)
}
return doHTTPRequest(method, uri, headers, reader)View on GitHub (pinned to 909b515798)
Solutions
- Pass headers as an expr map literal like {"Content-Type": "application/json"}, which produces map[string]any
- If you have a map[string]string, rebuild it as map[string]any before calling HTTPRequest
- Ensure all four arguments (method, url, headers, body) are provided so headers isn't a missing/nil param
- Wrap header construction so non-map values are converted or defaulted to an empty map
Example fix
// before (map[string]string rejected)
HTTPRequest("POST", url, map[string]string{"X-Token": token}, "")
// after
HTTPRequest("POST", url, {"X-Token": token}, "") Defensive patterns
Strategy: type-guard
Validate before calling
hdrs, ok := args[2].(map[string]any)
if !ok {
return fmt.Errorf("headers must be a map[string]any, got %T", args[2])
} Type guard
func isHeaderMap(v any) bool {
_, ok := v.(map[string]any)
return ok
} Try / catch
resp, err := exprhelpers.HTTPRequest(method, url, headers, body)
if err != nil {
if strings.HasPrefix(err.Error(), "invalid type for headers") {
// fall back to default headers or skip request
}
return err
} Prevention
- Always build headers as expr map literals: {"K": "v"}
- Never pass map[string]string to expr HTTP helpers
- Supply all four HTTPRequest arguments so params don't shift
- Unit-test expr expressions with TestHTTPRequest-style calls before deploying
When it happens
Trigger: Calling HTTPRequest with params[2] not of type map[string]any: passing a map[string]string literal, passing nil as headers, or passing an expr expression that evaluates to something other than a map (e.g. a slice or struct).
Common situations: Writing expr helper calls by hand and supplying headers as map[string]string (a common Go habit), forgetting the headers argument so nil is passed, or piping a parsed JSON object whose dynamic type isn't map[string]any.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- invalid type for url: %T
- invalid type for contentType: %T
- invalid type for body: %T
- invalid type for method: %T
- AverageInterval expects a slice of times
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/513ffa8f08bd6cb0.
Report an issue: GitHub.