WordPress page slug conflicts with media library item

I created a new page which is assigned a custom template. When I visit that page’s url I see what appears to be the default page layout (not my template) and the admin toolbar shows options pertaining to media (ex: Edit media).

After some head scratching, I deduced that somehow that url must point to a media item. I edited the page slug and “bingo” the actual page appears just as expected. When I visit the original url (from the first slug) I see the same media item.

Read More

Bottom line: It appears that coincidentally the page and the media item share the same name, and this was somehow causing WP’s wires to get crossed.

My question: Can someone help me understand how/why this happens? Does wordpress create magic permalinks to everything in the media library (other than their location in wp-content/uploads/...)?

Note: The media item was uploaded normally into the media library (not FTP into the root directory, etc)

Related posts

Leave a Reply

4 comments

  1. Yes, in WordPress you cannot have duplicate slugs/categories/taxonomies/tags. So if your theme allows for media files and permalinks to have their own page and the slug is the same as another one, it will usually append a number to it because the database does not like it.

    media slug “example”
    page slug “example” will not work since that slug exists already , if done in the admin it will automatically change the slug to “example-1”.

  2. I just had this problem and fixed it like this:

    $post_s=get_posts('posts_per_page=-1');
            foreach($post_s as $p){
                $atts = get_posts('post_type=attachment&name='.$p->post_name.'&posts_per_page=-1&post_status=inherit');
                foreach($atts as $att){
                    echo 'found!! '.$p->post_name;
                    // Update post 37
                    $my_post = array(
                          'ID'           => $atts->ID,
                          'post_name' => $att->post_name.'-image'
                    );
                    // Update the post into the database
                    wp_update_post( $my_post );
                }
            }
    
  3. This is a late answer, but I wanted to give a cleaner version of the answer that alesub gave.

    function wp21418_append_to_post_name() {
    
        // Checks to see if the option images_updated has been set or has a value of true.
        if ( get_option( 'images_updated' ) === 'true' ) :
            return;
        endif;
    
        // get all attachment posts.
        $attachments = get_posts([
            'post_type' => 'attachment',
            'post_status' => 'inherit',
            'name' => $p->slug,
            'posts_per_page' => -1,
        ]);
    
        // For each attachment, loop and update the post_name
        foreach($attachments as $p){
    
            $attachment = array(
                'ID'           => $p->ID,
                'post_name' => $p->post_name.'-image'
            );
            // Update the post into the database
            wp_update_post( $attachment );
    
        }
    
        // Once everything is looped, add the option to the database.
        add_option( 'images_updated', 'true' );
    }
    
    add_action( 'after_setup_theme', 'wp21418_append_to_post_name' );
    

    This function runs on an action hook right after the theme has setup. The first line checks to see if there is an option in the database images_updated. If that option exists, we bail on the function and it doesn’t do any processing. Otherwise, if the option does not exist, it runs the function and sets the option at the very end.

    This makes it so it will only run once. You don’t have to remove the function after refresh. If you want to run it again, you can simply remove the if statement at the top. As a caveat: doing this will add another -image at the end of post_names even if they have -image already (e.g. -image-image)

    There could be more file name checking for that situation. Will update the answer with that if someone really needs it.

  4. I tried one of the suggested solutions, and ended up having attachment pages like /bob-image-image-image-image/.

    I’d suggest that instead of using alesub or disinfor’s code blindly, use a better option in the form of “Disable Media Pages” plugin.

    https://github.com/joppuyo/disable-media-pages

    It automatically sets all attachment slugs to an unique id, and there is the option to mangle any existing attachment slugs so they won’t cause any issues in the future.