Skip to content

URL-to-post lookups cache resolutions for a week without invalidation #4663

Description

@acicovic

Describe the bug

Utils::get_post_id_by_url() caches its result under url-to-postid-<hash> for WEEK_IN_SECONDS, in two places: src/Utils/class-utils.php:446 for the url_to_postid() match, and :481 for the slug match. Nothing invalidates that key — there is no wp_cache_delete() for it, and no hook on post changes.

A cached resolution can therefore disagree with the site for up to a week after the post behind a URL changes. Visibility is checked on return, so this is a freshness and correctness issue rather than an access one.

To Reproduce

On a site with a persistent object cache:

  1. Create a private page with the slug example-slug.
  2. Resolve a URL ending in /example-slug/ through any feature that maps URLs to posts, so the result is cached.
  3. Publish a post with the same slug. WordPress keeps slugs unique only within a post type, so a page and a post can share one.
  4. Resolve the same URL again.

The lookup keeps returning the earlier resolution until the entry expires. Clearing the object cache returns the expected post.

The same cause affects neighbouring cases: a cached post that is later unpublished, deleted, or given a different slug.

Expected behavior

The lookup reflects the current state of the site, or the cached entry is invalidated when the posts behind it change.

Environment

wp-parsely 3.24.x, any WordPress version. Only observable on sites with a persistent object cache; without one the entry lasts a single request.

Additional context

Raised by CodeRabbit on #4662.

Possible directions: invalidate the key on save_post/deleted_post, shorten the TTL, or key the entry so that a stale hit cannot occur. Addressing it at a single call site would leave the other paths above untouched.

Activity

  1. added
    BugTicket that is a bug report
    wp-parselyRequired label for all issues
    on Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugTicket that is a bug reportwp-parselyRequired label for all issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions