Apex compile error

Method does not exist or incorrect signature: ...

"Method does not exist or incorrect signature" — the eight causes

This is a compile-time error: the Apex compiler sees the call site but can't resolve it to a method on the variable's declared type. Eight things produce it. Walk this list in order; one of them is your bug.

Quick triage

Read the error message carefully: it tells you the type the compiler thinks the variable is, and the argument types it tried to match. Most of the time, the type is broader than you expect (SObject instead of Account, Object instead of your class) and the fix is a cast.

The eight causes

1. Typo or wrong case

User-defined types in Apex are case-insensitive at the type/identifier level, but managed package methods, namespaces, and constants are not always treated identically. Double-check the spelling — easy to miss in a long argument list.

2. Wrong argument types or count

The error message ends with the argument types it tried to match. If it shows (String, Integer) but the method takes (String, Long), that's your bug. Apex auto-coerces some types (Integer → Long) but not others. Cast explicitly:

apex
// Fails: passing Integer where Decimal expected and no implicit widening
calculator.compute(5);

// Works
calculator.compute((Decimal) 5);
calculator.compute(5.0);

3. The variable is typed as a parent type — you need a cast

The most common cause in real code. You SOQL into SObject, you iterate over List<SObject>, you accept an Object argument — and the compiler can only see methods on those declared types.

apex
SObject record = [SELECT Id, Name FROM Account LIMIT 1];

// Fails: SObject doesn't declare getName()
String n = record.getName();

// Works: cast to Account first
Account a = (Account) record;
String n = a.Name;

4. Static called on instance (or vice versa)

Apex enforces this strictly. System.debug(...) is static — System sys = new System(); sys.debug(...) won't compile. Custom classes get it both ways: an instance method called as MyClass.method(), or a static called as (new MyClass()).method() — both surface as "method does not exist".

5. Method is private or protected, and you're outside its scope

The compiler treats a method it can't see the same way as a method that doesn't exist. If your test class calls a private helper, the error reads identically to a typo. Mark the method @TestVisible (visible only to tests) or promote it to public:

apex
public class OrderService {
  @TestVisible
  private void calculateDiscount(Order o) { /* ... */ }
}

// OrderServiceTest can now call calculateDiscount

6. Generic type erasure — the silent killer

Apex generics are reified only for collection types. Pass a List<Account> into a method that accepts List<SObject>and the method body sees List<SObject> — calls to Account-specific methods fail. Same for Map<Id, Account> vs Map<Id, SObject>. Either cast inside the loop, or make the helper generic by accepting the concrete type.

apex
public static void process(List<SObject> records) {
  for (SObject r : records) {
    // Account a = r.Account; // doesn't compile
    Account a = (Account) r;  // ok
    System.debug(a.Name);
  }
}

7. Managed-package method missing the namespace prefix

When your code lives outside a managed package and the method is defined inside one, you must prefix the namespace. fflib_SObjectUnitOfWork.registerNew(...) someNamespace.fflib_SObjectUnitOfWork.registerNew(...). Subscriber-org code that fails on the same line that works in the package source is almost always this.

8. A field or property shadows the method name

Rare but real: declaring String getName; as a field in the same class as a method String getName() makes the field win — calls to the method now hit the field reference and the compiler complains the method doesn't exist with () applied. Rename the field.

How to read the error message

The error has a strict shape. Knowing the parts helps you triage in seconds:

text
Method does not exist or incorrect signature:
  void buildSummary(String, Integer)
  from the type OrderService
  • The return type (void) is what the call site expected — usually the assignment target.
  • The arguments in parens are the types the compiler inferred from what you passed in. If one of them is unexpectedly broad (Object, SObject), that's a clue.
  • The type after "from the type" is what the compiler thinks your variable is. If that's not what you expect, cast at the call site.

Catch this at write time — not at deploy time

Salesforce only reports compile errors after you save to the org or run a deploy. Nimbus type-checks Apex locally and the LSP highlights "method does not exist" the moment you type it. Same diagnostic, no round-trip.

bash
# One-shot type-check before commit
nimbus check

# Or run the LSP and get diagnostics live in VS Code / IntelliJ
nimbus lsp