The remove_action() function allows you to disable a callback that was previously added with add_action(). This is useful when you need to change a plugin or theme’s behavior without editing its files.
In practice, remove_action() often appears to “not work” because WordPress looks for a callback using an exact set of parameters: the hook name, function or method, priority, and execution timing. If even one element does not match, the callback will not be removed.
How remove_action() Works
When add_action() is called, WordPress stores the callback in the internal list for a specific hook. This record includes the hook name, callback, and priority. remove_action() does not remove a “similar” function; it searches for the exact record that was previously added.
The function signature is:
- the hook name must be identical;
- the function, method, or object must match;
- the priority must be the same as the one used with add_action();
- the removal must take place after the callback has been registered but before it actually runs.
remove_action( string $hook_name, callable $callback, int $priority = 10 ): bool;
An Incorrect Priority Is the Most Common Cause
If the callback was added with a priority of 20, you cannot remove it with a priority of 10. The default value in remove_action() is 10, so omitting the third argument is often the cause of the problem.
It is also important to distinguish between the time a callback is registered and the time it runs. In the example below, the callback is registered on init with a priority of 20 and removed on the same hook with a priority of 30. During the first init execution, the callback with priority 20 will already have run. The removal will affect only subsequent executions of this hook, if any occur.
- To prevent a callback from running, remove it before WordPress reaches its priority.
- If third-party code adds a callback during init, removing it at a later priority will not cancel an action that has already run.
- For one-time hooks such as init, removing a callback too late usually does not produce the expected result.
add_action( 'init', 'plugin_register_post_type', 20 );
// This code runs after the callback with priority 20.
add_action( 'init', function () {
remove_action( 'init', 'plugin_register_post_type', 20 );
}, 30 );
Check Exactly When the Callback Is Added
remove_action() must be called after add_action(); otherwise, WordPress does not yet have a record to remove. At the same time, the removal must happen early enough for the callback not to run.
For example, a plugin may register its callback on plugins_loaded, init, wp_loaded, or a custom hook. If your code runs earlier, the callback does not exist yet. If it runs significantly later, the callback may already have been executed.
The best approach is to find the add_action() line in the plugin’s code and trace the entire sequence: where it runs, what priority it uses, and which hook provides a safe opportunity to intervene.
- If the callback is added during plugins_loaded, your removal code must run after that point.
- If the callback is added on init, removing it on init at a later priority may be too late for the current execution.
- If the action has already changed data or registered a post type, remove_action() will not restore the previous state—it only prevents future calls.
add_action( 'plugins_loaded', function () {
remove_action( 'some_hook', 'plugin_callback', 10 );
}, 20 );
How to Check Whether a Callback Is Registered
Use has_action() for a quick check. The function returns the callback’s priority if it is found, or false if no such record exists. Because add_action() in WordPress uses the same underlying mechanism, has_action() is also suitable for diagnosing actions.
It is best to perform the check immediately before remove_action() and log the result. This helps distinguish an incorrect callback from a problem with execution timing.
- A value of false means that no callback was found with this description.
- A number indicates the priority that is actually registered.
- If the priority differs from the expected value, pass the registered priority to remove_action().
$priority = has_action( 'init', 'plugin_register_post_type' );
error_log( var_export( $priority, true ) );
if ( false !== $priority ) {
remove_action( 'init', 'plugin_register_post_type', $priority );
}
Object Methods and Anonymous Functions
A callback often belongs not to a global function but to an object. In that case, you must pass the same object instance. Creating a new instance of the same class and using the same method will not help: WordPress treats it as a different callable.
A static method uses different syntax from a method belonging to a specific object. You must also account for namespaces: the function name may include a namespace prefix.
- An object method requires the same instance.
- For a static method, use [ ClassName::class, 'method' ] or the corresponding string.
- An anonymous function can be removed only if it was stored in a variable.
- Creating a new closure with identical code is not enough: it will be a different function object.
$plugin_object = new Plugin_Class();
add_action( 'init', [ $plugin_object, 'register' ], 10 );
// The exact same $plugin_object is required.
remove_action( 'init', [ $plugin_object, 'register' ], 10 );
$callback = function () {
// Action.
};
add_action( 'init', $callback, 10 );
remove_action( 'init', $callback, 10 );
Action and Filter: What Exactly Should Be Removed
In WordPress, add_action() and add_filter() use the same underlying mechanism. At the API level, however, it is still best to use the corresponding pair: remove a callback added with add_action() using remove_action(), and remove a callback added with add_filter() using remove_filter(). This makes the code clearer and less prone to errors.
What matters is not the name of the removal function but the exact match between the hook name, callback, and priority. If the callback was added to a filter, check that exact filter and do not confuse it with an action that has a similar name.
The accepted_args parameter does not need to be passed to remove_action() or remove_filter(). WordPress uses the hook, callable, and priority to find the callback.
- Check that similar hook names have not been confused.
- Do not try to remove a filter through another hook with the same callback.
- If a callback is added multiple times with different priorities, each record must be removed separately.
add_filter( 'the_content', 'plugin_modify_content', 20 );
remove_filter( 'the_content', 'plugin_modify_content', 20 );
A Practical Troubleshooting Algorithm
When remove_action() produces no result, do not immediately change the priority at random. A systematic check will help you find the cause faster.
- Find the original add_action() call in the plugin or theme code.
- Copy the exact hook name and callback.
- Check the priority—if it is not specified, it is 10.
- Determine whether the callback is a regular function, an object method, a static method, or a closure.
- Check whether your code runs after the callback is registered but before it runs.
- Use has_action() and inspect its result.
- Make sure the action has not already run and changed the system state.
- After testing, limit the removal with the appropriate condition, environment, or specific context.
add_action( 'wp_loaded', function () {
$priority = has_action( 'some_hook', [ $same_object, 'method' ] );
error_log( 'Callback priority: ' . var_export( $priority, true ) );
if ( false !== $priority ) {
remove_action( 'some_hook', [ $same_object, 'method' ], $priority );
}
}, 20 );
Using remove_action() Safely
Removing a callback globally can affect every page and function on the site. Before making the change, check why the action is needed, whether other code depends on it, and in which context it should be disabled.
If the change is required only for the administrative area, a specific post type, or an individual template, add the appropriate condition. This reduces the risk of side effects after a plugin update.
- Do not edit third-party plugin files—put the code in your own plugin or theme.
- Test changes in a staging environment.
- Log the verification result during troubleshooting, but do not leave unnecessary logging enabled in production.
- After updating the plugin, verify the callback name, priority, and registration method again.
add_action( 'wp', function () {
if ( ! is_singular( 'product' ) ) {
return;
}
remove_action( 'some_hook', 'plugin_callback', 10 );
}, 20 );
Frequently asked questions
Can remove_action() be called before add_action()?
Usually, no. If the callback has not yet been registered, WordPress will not find it and nothing will be removed. However, it is not enough to call remove_action() after add_action(); you must also do so before the callback actually runs.
Why does remove_action() return true if the action still runs?
Most often, the callback was added more than once, for example with different priorities, or it had already run before it was removed. Check all registrations and the execution timing.
Can an object method be removed by creating a new instance of the class?
No. A regular object method requires the same instance that was passed to add_action(). A new object with the same class and method has a different identity.
How can an anonymous function be removed?
Store the closure in a variable when registering it, then pass that same variable to remove_action(). An anonymous function declared again will not be the same callback.
Can remove_action() be used for a callback added with add_filter()?
Internally, these APIs use the same mechanism, but for clearer code use remove_filter() for a filter and remove_action() for an action. In either case, the hook, callback, and priority must match.
Conclusion
remove_action() works only when all parameters match exactly and the timing is correct. Check the original add_action() call, the priority, the callback type, and the specific object instance.
If the callback has already run, removing it will not undo the completed action. Therefore, the key to troubleshooting is determining not only what needs to be removed, but also when it needs to be removed.