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

  1. Rewrite the expression to use only explicit `&&` and `||` operators with parenthesized grouping.
  2. If embedding the interpreter, check your actionlint version matches the one act vendors; pin/downgrade actionlint.
  3. 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

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


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/fdc8bfa38d686a09. Report an issue: GitHub.