Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Apex

Method does not exist or incorrect signature

The Apex compiler can't find a method matching the call you wrote — wrong name, wrong argument types, or wrong number of arguments. The compiler points at the line; the fix is usually a typo or a stale signature.

Also seen asMethod does not exist or incorrect signature·Method does not exist·incorrect signature apex

The compiler stops on a single line: account.getOwnerName(). The error reads Method does not exist or incorrect signature: void getOwnerName() from the type Account. You wrote that method yourself an hour ago. Or so you thought. You open the source, search for getOwnerName, and find it on a different class. Your call site is on Account. The compiler is right; the method doesn't exist on Account.

What the compiler is checking

When Apex sees expr.methodName(args), the compiler does three things:

  1. Resolves the static type of expr. For account, the type is Account (assuming no explicit cast).
  2. Searches that type's method table for a method named methodName.
  3. Among matching names, picks the overload whose parameter list matches the argument types.

If step 2 finds no method, you get Method does not exist. If step 2 finds a method but step 3 can't match an overload, you get incorrect signature. The error message names both cases because the compiler can't always tell which is more likely.

The check is at compile time, against the static type of the receiver. If you've got an SObject reference holding an Account at runtime but the variable's declared type is SObject, the compiler searches SObject's methods, not Account's. The cast matters.

The classic broken example

A common version of this bug, especially in code that uses dynamic SObject references:

public class AccountSummary {
    public static String describe(SObject record) {
        // Compiler refuses: Method does not exist or incorrect signature:
        //    void getName() from the type SObject
        return record.getName();
    }
}

The Account class has a Name field, accessible via .Name (field access) or .get('Name') (dynamic getter). It doesn't have a getName() method. The compiler refuses.

The variation that uses dynamic SObject methods:

public static String describe(SObject record) {
    return (String) record.get('Name'); // Works
}

This compiles because SObject declares a get(String) method.

Three sub-cases that produce the same error

Most appearances of "Method does not exist" come from one of these three patterns. Knowing which one is yours speeds the fix.

Wrong receiver type. The method exists, but on a different class than the one you're calling against. String.valueOf(myInt) works; myInt.valueOf() doesn't, because valueOf is a static method on String, not an instance method on Integer. The fix is to call the method on the right class.

Wrong argument types. The method name is right, but the arguments don't match any overload. System.assertEquals(expected, actual) takes two arguments of compatible types; calling System.assertEquals('foo') with one argument fails because no single-argument overload exists. The fix is to match the method's signature exactly.

The method was deleted or renamed. The call worked before someone refactored. The renamed method has a new signature; the old call site wasn't updated. The fix is to update the call site (or use the IDE's "Find usages" to catch this at refactor time).

The fix: a small checklist

When you see this error, walk this list in order:

  1. Open the class that owns the method. Does the method exist?
  2. Check the method's exact signature: name, parameter types in order, return type.
  3. Match against your call site's argument types. Are the types compatible?
  4. If the receiver is a generic SObject, cast to the concrete type first.
  5. Confirm the method is public (or global for managed packages) so it's visible to the caller.

For instance methods, also verify you're calling on the right kind of object. Static methods belong to a class; instance methods belong to an instance. Database.update(records) is a static call; someAccount.update() doesn't compile because there's no instance update method on Account.

The fixed example

Take the broken AccountSummary.describe and rewrite it with proper typing:

public class AccountSummary {
    public static String describe(SObject record) {
        if (record == null) return '(no record)';
        if (!(record instanceof Account)) {
            return 'Not an Account: ' + record.getSObjectType();
        }
        Account a = (Account) record;
        return a.Name + ' in ' + a.Industry;
    }
}

The fix: cast to the concrete type, then use field access. The compiler now searches Account's field list, finds Name and Industry, and compiles cleanly.

If the method genuinely needs to work on any SObject, use the dynamic getter:

public class AccountSummary {
    public static String describe(SObject record, String fieldName) {
        if (record == null) return '(no record)';
        Object value = record.get(fieldName);
        return value == null ? '(empty)' : value.toString();
    }
}

Dynamic access has runtime cost (no compile-time type check, slower lookup), but it works for any field on any SObject. Use it when the type is genuinely unknown at compile time.

Where overload resolution surprises people

Apex supports method overloading: multiple methods with the same name and different parameter lists. Overload resolution picks the best match. The rules:

  • Exact type match wins.
  • Then implicit widening conversions (e.g., Integer to Long).
  • Then user-defined casts.

If two overloads tie, the compiler reports ambiguity instead of picking arbitrarily. The error message in that case is different (Multiple overloaded methods are equally applicable), but the family is similar: the compiler can't resolve the call.

A subtle case: passing null to an overloaded method. myMethod(null) is ambiguous when there are two overloads taking different reference types. The compiler doesn't know which one you meant. Cast the null to disambiguate: myMethod((String) null).

SOQL bind variables versus method calls

A frequent source of "Method does not exist" is mixing up the bind-variable syntax in SOQL with method-call syntax in Apex:

// Compiler refuses: Method does not exist or incorrect signature
String name = 'Acme';
Account a = [SELECT Id FROM Account WHERE Name = name LIMIT 1];

Without the : prefix, the SOQL parser treats name as the literal string "name", not the Apex variable. With the colon, it's a bind variable:

Account a = [SELECT Id FROM Account WHERE Name = :name LIMIT 1];

The error message you see depends on whether name happens to match a field name. Sometimes you get Method does not exist, sometimes Unknown error parsing query. The cure is the same: prefix the bind variable with a colon.

The interaction with managed packages

A method declared public in a managed package isn't visible to consumers of that package. Only methods declared global are visible across namespace boundaries. If you've installed a managed package and you're trying to call one of its methods that the documentation mentions, but the compiler says "Method does not exist," check the method's modifier.

The fix is either to use a globally-exposed alternative or to contact the package vendor for an updated API.

For your own managed packages: if a consumer needs to call a method, mark it global, not public. Otherwise the method is invisible outside the namespace, which is the same as not existing.

Tooling that catches this earlier

The Salesforce VS Code extension's IntelliSense catches almost every "Method does not exist" error at typing time. The squiggly red underline appears as soon as you finish typing the method name. If you're hitting this error at deploy time, you're skipping a phase of feedback that the tooling provides for free.

For CI, the Apex compiler runs as part of sf project deploy validate. Running validate before pushing catches the error before it lands on a teammate's terminal. The investment of running validate is two minutes per change; the savings is hours of post-deploy triage when a "small" change broke a far-flung call site.

A subtle source: API version mismatches on dependent classes

A method introduced in a recent API version might not exist in older API versions. String.format with five arguments works in API 50+; the same call in an API 30 class fails with "Method does not exist." The fix is to bump the calling class's API version to one that supports the method.

You can find a class's API version in its metadata XML or the Setup → Apex Classes page. Bumping should be done deliberately, because newer API versions can change behavior in other methods you didn't intend to update.

When inheritance confuses the picture

Apex supports class inheritance via extends. If a base class declares a method and a derived class doesn't override it, calling the method on a derived-class reference resolves to the base. So far, ordinary.

Where it gets tricky: virtual methods. If a base class declares public virtual void foo() and a derived class overrides with public override void foo(), the call dispatches dynamically at runtime. The compile-time check happens against the static type of the receiver, not the runtime type, but the method's body that runs is the derived class's.

If the override has a different signature (different parameter types or return type), Apex refuses to compile the override. So you can't accidentally "shadow" a base method with an incompatible signature; the compiler catches it.

The interaction with "Method does not exist" surfaces when you cast incorrectly. A base-class reference holding a derived-class instance can only call base-class methods directly:

public virtual class Animal {
    public virtual String sound() { return 'generic'; }
}
public class Dog extends Animal {
    public override String sound() { return 'woof'; }
    public String fetchObject() { return 'ball'; }
}

Animal a = new Dog();
String s = a.sound();         // OK: 'woof' via dynamic dispatch
String t = a.fetchObject();   // Method does not exist on Animal

The fix is to cast: ((Dog) a).fetchObject() or to redesign so the method belongs on the base.

A debugging trick when the message is misleading

If the call site looks correct and you can't see what's wrong, paste both the calling code and the called method into the Developer Console's Anonymous Apex window and add a System.debug(methodName); line. The compile error on Anonymous Apex sometimes carries more detail than the deploy error, and the iteration is faster.

The Apex Replay Debugger in VS Code can also step through the compilation pipeline and surface intermediate errors. For very tangled cases with many overloads, it's worth the setup.

Visibility modifiers as a frequent cause

A method declared private is only callable within its own class. From outside, the compiler says "Method does not exist" because the method isn't visible. The signature is technically correct; the access modifier excludes it.

Common modifier confusion:

  • private: only the declaring class.
  • protected: the declaring class and its subclasses.
  • public: anywhere in the namespace.
  • global: anywhere, including outside the namespace (used for managed-package APIs).

If you're getting "Method does not exist" from a call site that you're sure points at the right method, double-check the modifier. A teammate may have tightened the visibility during a refactor.

Further reading from Salesforce

Related dictionary terms

Share this fix

Share on LinkedInShare on X

Related Apex errors