{"record":{"id":"fdc8bfa38d686a09","repo":"nektos/act","slug":"unable-to-compare-incompatibles-types-s-and-s","errorCode":null,"errorMessage":"Unable to compare incompatibles types '%s' and '%s'","messagePattern":"Unable to compare incompatibles types '(.+?)' and '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/exprparser/interpreter.go","lineNumber":607,"sourceCode":"\tif IsTruthy(left) == (compareNode.Kind == actionlint.LogicalOpNodeKindOr) {\n\t\treturn impl.getSafeValue(leftValue), nil\n\t}\n\n\tright, err := impl.evaluateNode(compareNode.Right)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trightValue := reflect.ValueOf(right)\n\n\tswitch compareNode.Kind {\n\tcase actionlint.LogicalOpNodeKindAnd:\n\t\treturn impl.getSafeValue(rightValue), nil\n\tcase actionlint.LogicalOpNodeKindOr:\n\t\treturn impl.getSafeValue(rightValue), nil\n\t}\n\n\treturn nil, fmt.Errorf(\"Unable to compare incompatibles types '%s' and '%s'\", leftValue.Kind(), rightValue.Kind())\n}\n\n//nolint:gocyclo\nfunc (impl *interperterImpl) evaluateFuncCall(funcCallNode *actionlint.FuncCallNode) (interface{}, error) {\n\targs := make([]reflect.Value, 0)\n\n\tfor _, arg := range funcCallNode.Args {\n\t\tvalue, err := impl.evaluateNode(arg)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\targs = append(args, reflect.ValueOf(value))\n\t}\n\n\tswitch strings.ToLower(funcCallNode.Callee) {\n\tcase \"contains\":\n\t\treturn impl.contains(args[0], args[1])","sourceCodeStart":589,"sourceCodeEnd":625,"githubUrl":"https://github.com/nektos/act/blob/4f411281417e88660bea1c1a1749aa71ae0bd60f/pkg/exprparser/interpreter.go#L589-L625","documentation":"Thrown by evaluateLogicalCompare when a LogicalOpNode's Kind is neither And nor Or after the left operand failed the truthiness short-circuit. The function short-circuits `&&`/`||` correctly; reaching the trailing return means the actionlint AST produced a logical-op node kind the interpreter does not map (e.g. a new/unexpected LogicalOpNodeKind value). It is effectively an internal invariant violation rather than a user input error.","triggerScenarios":"Evaluating an expression containing a logical operator whose actionlint node Kind is not LogicalOpNodeKindAnd or LogicalOpNodeKindOr (for example a Not node routed through this path, or a node kind introduced by a newer actionlint version). Only reachable when the left operand does not short-circuit.","commonSituations":"Upgrading the actionlint dependency introduces a new logical-op node kind; hand-constructed ASTs passed to the interpreter; expressions mixing `!` with `&&`/`||` on an incompatible parser path.","solutions":["Rewrite the expression to use only explicit `&&` and `||` operators with parenthesized grouping.","If embedding the interpreter, check your actionlint version matches the one act vendors; pin/downgrade actionlint.","Report the expression and act version upstream — this path indicates an interpreter/AST mismatch, not a workflow bug."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := interpreter.Evaluate(expr); err != nil && strings.Contains(err.Error(), \"Unable to compare incompatibles types\") {\n    // interpreter/AST mismatch — report act version and expression upstream\n}","preventionTips":["Keep expressions limited to && and || with explicit parentheses.","Pin the actionlint version act vendors when embedding; upgrade act and actionlint together."],"tags":["expression","exprparser","logical-operators","internal"],"backgroundTag":null,"analyzedSha":"4f411281417e88660bea1c1a1749aa71ae0bd60f","analyzedAt":"2026-08-15T09:19:46.307Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}