nektos/act · error
Unable to compare incompatibles types '%s' and '%s'
Error message
Unable to compare incompatibles types '%s' and '%s'
What it means
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.
Source
Thrown at pkg/exprparser/interpreter.go:607
if IsTruthy(left) == (compareNode.Kind == actionlint.LogicalOpNodeKindOr) {
return impl.getSafeValue(leftValue), nil
}
right, err := impl.evaluateNode(compareNode.Right)
if err != nil {
return nil, err
}
rightValue := reflect.ValueOf(right)
switch compareNode.Kind {
case actionlint.LogicalOpNodeKindAnd:
return impl.getSafeValue(rightValue), nil
case actionlint.LogicalOpNodeKindOr:
return impl.getSafeValue(rightValue), nil
}
return nil, fmt.Errorf("Unable to compare incompatibles types '%s' and '%s'", leftValue.Kind(), rightValue.Kind())
}
//nolint:gocyclo
func (impl *interperterImpl) evaluateFuncCall(funcCallNode *actionlint.FuncCallNode) (interface{}, error) {
args := make([]reflect.Value, 0)
for _, arg := range funcCallNode.Args {
value, err := impl.evaluateNode(arg)
if err != nil {
return nil, err
}
args = append(args, reflect.ValueOf(value))
}
switch strings.ToLower(funcCallNode.Callee) {
case "contains":
return impl.contains(args[0], args[1])View on GitHub (pinned to 4f41128141)
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.
Defensive patterns
Strategy: try-catch
Try / catch
if _, err := interpreter.Evaluate(expr); err != nil && strings.Contains(err.Error(), "Unable to compare incompatibles types") {
// interpreter/AST mismatch — report act version and expression upstream
} Prevention
- Keep expressions limited to && and || with explicit parentheses.
- Pin the actionlint version act vendors when embedding; upgrade act and actionlint together.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Compare not implemented for types: left: %+v, right: %+v
- TODO: '%s' not implemented
- Invalid glob option %s, available option: '--follow-symbolic
- failed to insert node %v into mapping %v unexpected type %v
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/fdc8bfa38d686a09.
Report an issue: GitHub.