Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Flow

The Apex action <name> couldn't be invoked because it's not @InvocableMethod or has the wrong signature

A Flow tried to call an Apex method as an action, but the method either lacks the `@InvocableMethod` annotation, doesn't return / accept a `List` (Invocable methods are bulkified by contract), or its parameter type isn't supported. The fix is to refactor the Apex method into invocable shape.

Also seen asApex action couldn't be invoked·InvocableMethod·wrong signature flow apex·The flow tried to call an Apex action

Flow's "Apex Action" elements call public static Apex methods marked @InvocableMethod. The Flow runtime is strict about the shape: the method must accept List<X> and return List<Y> (or void). It can't accept individual records.

The required shape

public class FlowExpensiveCalc {
    @InvocableMethod(
        label='Compute total'
        description='Sums the Amount of related opportunities'
    )
    public static List<Output> run(List<Input> inputs) {
        List<Output> results = new List<Output>();
        for (Input i : inputs) {
            Output o = new Output();
            o.total = computeTotal(i.accountId);
            results.add(o);
        }
        return results;
    }

    public class Input {
        @InvocableVariable(required=true) public Id accountId;
    }

    public class Output {
        @InvocableVariable public Decimal total;
    }
}

Three rules to live by:

  1. Method must be public static.
  2. Method must accept exactly one parameter, of type List<X>. X is your inner Input class with @InvocableVariable-annotated fields.
  3. Method must return void or List<Y> where Y has @InvocableVariable fields.

Why bulk?

Flow's invocable framework batches calls. If 200 records all flow into the same Apex Action node, the platform calls your method once with a 200-element list. If you wrote it as public static Output run(Input i), the framework couldn't batch — and would (in older versions) refuse to compile, in newer versions throw at runtime.

The classic mistake

// ❌ Flow can't call this — wrong signature
@InvocableMethod
public static void doStuff(Id accountId) { ... }

The fix:

// ✅
@InvocableMethod
public static void doStuff(List<Id> accountIds) { ... }

Or with structured input:

@InvocableMethod
public static void doStuff(List<Request> requests) { ... }

public class Request {
    @InvocableVariable(required=true) public Id accountId;
    @InvocableVariable public String reason;
}

The structured-input form is preferred because each @InvocableVariable shows up as a labelled field in the Flow UI when admins configure the action.

A subtler cause: changed signature, not redeployed

If you changed the Apex method's signature in a deploy that didn't include the flow, the flow's stored config now points at a non-existent method shape. The flow tries to call run(List<OldInput>) but the class has run(List<NewInput>). Same error. Fix: deploy the flow alongside the Apex change and reactivate it.

When the failure is in production but not sandbox

Flows track active version per environment. If you tested with version 5 in sandbox, deployed version 5 to production, but production was still on version 4 (because production deploys don't auto-activate flows in some configs), the live flow is calling the old API. Activate the deployed version in production: Setup → Flows → flow → Activate.

A debugging path

  1. Confirm the Apex method exists in the target org: query ApexClass by name.
  2. Confirm the method's signature: read the source.
  3. Confirm @InvocableMethod is present and the parameter is List<...>.
  4. Confirm the inner Input/Output classes have @InvocableVariable on every public field the flow uses.
  5. Re-import the action in Flow Builder so it picks up the current shape.

Related dictionary terms