crowdsecurity/crowdsec · error
unable to build %s hook : %w
Error message
unable to build %s hook : %w
What it means
buildHookList compiles every hook of a stage via hook.Build (filter/apply expr compilation, apply-rule setup). If any hook fails to build, the stage build aborts and the underlying error is wrapped with the stage name (pre_eval, post_eval, on_match). This is a wrapper: look at the wrapped error (e.g. expr compile failure) for the root cause.
Source
Thrown at pkg/appsec/appsec.go:836
wc.OutOfBandOptions.RequestBodyInMemoryLimit = wc.OutOfBand.Options.RequestBodyInMemoryLimit
}
wc.VariablesTracking = append(wc.VariablesTracking, wc.OutOfBand.VariablesTracking...)
wc.OutOfBand.VariablesTracking = nil
}
}
// buildHookList validates and compiles a list of hooks of the given stage.
func buildHookList(ctx context.Context, hooks []Hook, stage hookStage, patcher *appsecExprPatcher) ([]Hook, error) {
var compiled []Hook
for _, hook := range hooks {
if hook.OnSuccess != "" && hook.OnSuccess != "continue" && hook.OnSuccess != "break" {
return nil, fmt.Errorf("invalid 'on_success' for %s hook : %s", stage, hook.OnSuccess)
}
if err := hook.Build(ctx, stage, patcher); err != nil {
return nil, fmt.Errorf("unable to build %s hook : %w", stage, err)
}
compiled = append(compiled, hook)
}
return compiled, nil
}
// buildPhaseHooks compiles pre_eval / post_eval / on_match hook lists into a
// PhaseHooks. phaseName is only used to wrap errors ("" for the shared section).
func buildPhaseHooks(ctx context.Context, phaseName string, pre, post, onMatch []Hook, patcher *appsecExprPatcher) (PhaseHooks, error) {
var (
out PhaseHooks
err error
)
wrap := func(e error) error {
if phaseName == "" || e == nil {View on GitHub (pinned to 909b515798)
Solutions
- Look at the wrapped (%w) inner error for the real cause and fix it (usually an expr compile error)
- Note the stage prefix in the message to locate the failing phase section in the YAML
- Validate each hook's filter/apply expressions individually with the expr CLI or a small Go test
- Bisect by commenting out hooks in that stage until the build succeeds
Defensive patterns
Strategy: try-catch
Prevention
- Inspect the wrapped root cause
- Dry-run build configs before deploy
When it happens
Trigger: Build() → buildPhaseHooks → buildHookList where one hook's Build returns an error: invalid expr filter/apply (672/673), a referenced rule file that fails to load, or invalid hook options.
Common situations: An appsec rule with a bad expr filter; hook referencing a missing variable or rule; broken YAML that unmarshaled into a hook with empty/invalid fields that Build rejects.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- on_challenge hooks are only valid in-band, not under outofba
- ref cannot be empty
- on_challenge_submit hooks are only valid in-band, not under
- max_body_size must be a positive integer
- empty master secret
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/ce8ff55f0a69635d.
Report an issue: GitHub.