Make WordPress Core

Opened 5 years ago

Last modified 5 years ago

#47988 new defect (bug)

Unexpected behaviour when draft post has the same page_name as published post

Reported by: ajfleming's profile ajfleming Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Posts, Post Types Keywords:
Focuses: Cc:


What steps should be taken to consistently reproduce the problem?

wp rewrite structure '/%postname%/'

wp post create --post_title="Example post title" --post_status=publish --post_name=my-chosen-post-name

wp post create --post_title="A draft post" --post_status=draft --post_name=my-chosen-post-name


In case it's relevant to the ticket, what is the expected output or result?

We're expecting the published post to be displayed.

What did you see instead?

If you're authenticated and have permission to view drafts, the draft post will populate the Global $post object and be displayed.

Anonymous users will get a 404 page or the browser will throw a Too many redirects error.

Does the problem occur even when you deactivate all plugins and use the default theme?


Please provide any additional information that you think we'd find useful. (OS and browser for UI defects, server environment for crashes, etc.)

The core behaviour of the WP Admin post edit screen doesn't allow us to get into this state because post_name values are not stored for a post until it transitions to the publish post status. When this transition does happen wp_unique_post_slug() ensures the post_name being saved unique.

We first encountered this issue via the Yoast SEO plugin metabox which allows a Slug to be saved for draft posts. As you can see with the WP-CLI commands above, however, there are other ways of getting to this state.

The draft post is loaded for authenticated requests because the default query vars order_by => post_date and order => DESC means the draft post created after the published post populates the WP_Query->post property.

Anonymous requests are not able to view the draft post, so before returning a 404, redirect_canonical() calls redirect_guess_404_permalink() which builds a query for a published post where page_name is LIKE the post name and finds the published post and redirects to it... and the loop continues.

Attachments (1)

47988-20190906-1249.diff (534 bytes) - added by ajfleming 5 years ago.
A possible solution would wp_unique_post_slug() returning an empty string for draft posts instead of the passed value.

Download all attachments as: .zip

Change History (2)

5 years ago

A possible solution would wp_unique_post_slug() returning an empty string for draft posts instead of the passed value.

#1 @SergeyBiryukov
5 years ago

  • Component changed from General to Posts, Post Types
Note: See TracTickets for help on using tickets.