I have been using this site alot for solving my problems, but this time I did not succeed in finding and answer for my problem.

I get and infinite loop when using wp_update_post inside a function that is called on save_post. I know that this is a common issue, but I can't figure out how to avoid it.

I want to save the order of my posts (which is of the post-type 'section'). So I have made a custom meta box which contain some sortable html-elements. In each element there is an hidden input tag with name='sectionorder[]'. So when I click the standard WordPress 'Update' buttom, an array containing all the ID's of the posts (in order) are send via POST. So here is the code where I retrieve the array, and wants to save the order:

    // Update section sort order
$sectionorder = $_POST['sectionorder'];
if (isset($sectionorder)) { // Avoid error if there is no sections added yet
    foreach( $sectionorder as $no => $sectionID ) {
        $post_update = array();
        $post_update['ID'] = $sectionID;
        $post_update['menu_order'] = $no;
        wp_update_post( $post_update );

But the problem is that it starts an infinite loop. How do I avoid that? Maybe I can do it in a completely different way?

Appriciate your help!

3 Answers 3


You can remove the callback from the save_post hook, update the post and then re-add the call back to the hook. The Codex gives an example.

add_action('save_post', 'wpse51363_save_post');

function wpse51363_save_post($post_id) {

    //Check it's not an auto save routine
     if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 

    //Perform permission checks! For example:
    if ( !current_user_can('edit_post', $post_id) ) 

    //Check your nonce!

    //If calling wp_update_post, unhook this function so it doesn't loop infinitely
    remove_action('save_post', 'wpse51363_save_post');

    // call wp_update_post update, which calls save_post again. E.g:
    wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));

    // re-hook this function
    add_action('save_post', 'wpse51363_save_post');
  • Wow. Thanks for the quick reply. Works like a charm! Don't know why I didn't see that code example myself..
    – elgehelge
    Commented May 7, 2012 at 11:08
  • @Stephen, I use update_post_meta in a function hooked to save_post should I also unhook and rehook after update_post_meta?
    – Anagio
    Commented Nov 14, 2013 at 19:20
  • No, update_post_meta won't (generally) cause save_post to be triggered. Commented Nov 14, 2013 at 19:49
  • After wasting an hour found this and this also saved more hours, thank you. Commented Dec 22, 2019 at 5:39
  • works for me, in the year 2020
    – gray
    Commented May 1, 2020 at 23:00

I haven't quite got the reputation to comment so I'm adding an answer even though Stephen's is excellent and correct. It just doesn't handle instances when you want to set the priority of the action.

If you set the priority when adding the action but don't specify priority when you remove it you will still get an infinite loop.

add_action('save_post', 'wpse51363_save_post', 25 );

// The WRONG way to handle this - leads to infinite loop

remove_action('save_post', 'wpse51363_save_post');
wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));
add_action('save_post', 'wpse51363_save_post');

// The RIGHT way to handle this - executes only once

remove_action('save_post', 'wpse51363_save_post', 25 );
wp_update_post(array('ID' => $post_id, 'post_status' => 'private'));
add_action('save_post', 'wpse51363_save_post', 25 );

This is a rather quick and dirty trick but one way is to create a global variable like $my_plugin_name_saving and just set it to true before calling wp_update_post and return if the variable is already set.

/* Plugin Name: My plugin name */

$my_plugin_name_saving = false;

function cc_publish_wpse_263985( $postid ) {
    global my_plugin_name_saving;

    if ( ! empty( $my_plugin_name_saving ) ) {

    $my_plugin_name_saving = true;
    wp_update_post(array('ID' => $postid, 'post_status' => 'private'));


add_action('save_post', 'cc_publish_wpse_263985');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.