{"record":{"id":"3cc0166e1094c940","repo":"crowdsecurity/crowdsec","slug":"assertion-s-is-not-a-condition","errorCode":null,"errorMessage":"assertion '%s' is not a condition","messagePattern":"assertion '(.+?)' is not a condition","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/hubtest/parser_assert.go","lineNumber":223,"sourceCode":"\tret, err := yaml.Marshal(output)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn string(ret), nil\n}\n\nfunc (p *ParserAssert) Run(assert string) (bool, error) {\n\toutput, err := p.RunExpression(assert)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tswitch out := output.(type) {\n\tcase bool:\n\t\treturn out, nil\n\tdefault:\n\t\treturn false, fmt.Errorf(\"assertion '%s' is not a condition\", assert)\n\t}\n}\n\nfunc Escape(val string) string {\n\tval = strings.ReplaceAll(val, `\\`, `\\\\`)\n\tval = strings.ReplaceAll(val, `\"`, `\\\"`)\n\n\treturn val\n}\n\nfunc (p *ParserAssert) AutoGenParserAssert() string {\n\t// attempt to autogen parser asserts\n\tret := fmt.Sprintf(\"len(results) == %d\\n\", len(*p.TestData))\n\n\t// sort map keys for consistent order\n\tstages := maptools.SortedKeys(*p.TestData)\n\n\tfor _, stage := range stages {","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/hubtest/parser_assert.go#L205-L241","documentation":"Run evaluates an assertion expression and expects the result to be a boolean. If the expr evaluation succeeds but the output is any other type (string, int, nil), the assertion cannot be interpreted as a pass/fail condition and this error is returned. It flags assertions written as expressions that return values rather than conditions.","triggerScenarios":"ParserAssert.Run called (by AssertFile) with an assertion whose expression evaluates to a non-bool, e.g. `Alert.GetValue()` alone, a string literal, or a comparison chain that expr reduces to a value.","commonSituations":"Assert files authored with bare expressions instead of equality/comparison conditions; auto-generated assertions after expr behavior changes; copy-pasted filter expressions into assert files.","solutions":["Rewrite the assertion as a boolean condition (comparison, ==, !=, and/or)","Check that top-level expression returns bool, e.g. wrap value: Alert.GetValue() == '1.2.3.4'","Run the expression via EvalExpression to see the actual output type","Fix auto-generation artifacts if the assert file was machine produced"],"exampleFix":"// before\nAlert.GetValue()\n// after\nAlert.GetValue() == '1.2.3.4'","handlingStrategy":"validation","validationCode":"out, err := p.RunExpression(assert)\nif err != nil { return false, err }\nif _, ok := out.(bool); !ok {\n    return false, fmt.Errorf(\"assertion %q must evaluate to a bool, got %T\", assert, out)\n}","typeGuard":"func isBool(v interface{}) bool { _, ok := v.(bool); return ok }","tryCatchPattern":"ok, err := p.Run(assertLine)\nif err != nil {\n    if strings.Contains(err.Error(), \"is not a condition\") {\n        return fmt.Errorf(\"fix assertion to return a bool: %v\", err)\n    }\n    return err\n}","preventionTips":["Write assertions as full comparisons, never bare value expressions","Check auto-generated asserts for non-bool expressions","Run each assert through EvalExpression and assert the %T is bool in CI"],"tags":["expr","assertion","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}