This is a pretty strange problem. I'm creating a WordPress custom post type in my themes functions.php file using the following format:

add_action('init', 'product_register');

function product_register() {
$args = array(
    'label' => __('Products'),
    'singular_label' => __('Product'),
    'public' => true,
    'show_ui' => true,
    'capability_type' => 'post',
    'hierarchical' => false,
    'rewrite' => true,
    'supports' => array('title', 'editor', 'thumbnail')

register_post_type( 'product' , $args );

This gives me the following url structure for my products: http://www.mywebsite.com/products/product-name.

However, if I switch to another theme (TwentyTen) and then switch back WordPress forgets the permalink, now when I browse to the URL above I get my 404 page.

The really strange thing I've noticed is that I can fix this issue by browsing to Settings -> Permalinks in admin. This temporarily fixes the problem until the next theme uninstall/ reinstall.

Anyone else had a similar issue?

  • This is a non-issue. What you described is normal. And healthy. Commented Oct 21, 2010 at 13:23
  • Also, it was probably just a typo, but, given the code you've pasted, the url above should say /product/ not /products/. Commented Oct 21, 2010 at 13:24
  • Hey John, yes that is a typo. The example url should be mywebsite.com/product/product-name.
    – jnthnclrk
    Commented Oct 21, 2010 at 13:26
  • I don't understand why WP forgets the permalink for the CPT. Surely, when I re-install my theme, functions.php should build the cpt and make the permalinks work as expected?
    – jnthnclrk
    Commented Oct 21, 2010 at 13:27
  • I don't appreciate getting a negative vote for a typo. The issue is still a problem for me, and I love some help figuring out how to fix it.
    – jnthnclrk
    Commented Oct 21, 2010 at 13:35

1 Answer 1


The new permalink structure is only saved when WP_Rewrite::flush_rules() is called. Because this is an expensive operation (calculating the new rules and saving them to the database), you should not do it on every init call, but only when you change the structure. The custom post type however must be registered at every init call, since it is saved in a PHP array in memory, not in the database (which is why it forgot the custom post when you switched themes: the permalink structure still existed but referred to a custom post type that was not loaded, giving an error).

  • Thank you! That explains why browsing to Settings -> Permalinks fixes it as flush_rules() gets called. Can you tell me how I should configure my Theme and CPT so users can uninstall and reinstall without getting this problem? I guess putting WP_Rewrite::flush_rules() in functions.php is a bad idea?
    – jnthnclrk
    Commented Oct 21, 2010 at 13:40
  • Or should I ask that as a separate question?
    – jnthnclrk
    Commented Oct 21, 2010 at 13:44
  • @trnsfrmr: Most people put this kind of code in a plugin, and then hook into the activation of that plugin via register_activation_hook(). This will "survive" theme changes. If you really want it in your theme, you could try hooking into the switch_theme action.
    – Jan Fabry
    Commented Oct 21, 2010 at 15:40
  • No need, I've fixed the problem by using the following line after my register_post_type call: flush_rewrite_rules( false );
    – jnthnclrk
    Commented Oct 21, 2010 at 15:48
  • @trnsfrmr: This works, but it is not recommended, because it takes some time to clear the database, re-calculate the rules and then save them again. Even if you don't do a "hard" flush (writing them to .htaccess), this requires database operations. So it really pays off to use the "proper" activation hooks.
    – Jan Fabry
    Commented Oct 21, 2010 at 18:50

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.