I have declared post type as below:

 $args = array(
        'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'query_var' => true,
        'rewrite' => array('slug' => 'agences'),
        'capability_type' => 'post',
        'has_archive' => true,
        'hierarchical' => false,
        'menu_position' => 5,
        'taxonomies' => array('brands', 'country'),
        'supports' => array('title', 'editor', 'author', 'thumbnail', 'custom-fields')

    register_post_type('destinations', $args);

Initially I was able to access single page of this post type using single-agences.php but now it is redirecting to 404.

I have checked other answers and found that its a common mistake but other answers were not able to resolve this. Any help will be wonderful.

  • 1
    Because you are not using the default rewrite rules, you need to flush and rebuild them. See this: custom_post_type with has_archive doesn't change permalink
    – cybmeta
    Mar 7, 2016 at 14:42
  • Your single file should be single-destinations.php, not with the rewrite rule. And your whole code should be inside a init hooked function. Mar 7, 2016 at 18:47
  • I tried single-destinations.php before trying single-agences.php but that was not working. even if it does not use these file it should use single.php but its giving a 404 error. and yes code is in init hooked funtion.
    – Deepak jha
    Mar 7, 2016 at 18:55

2 Answers 2


Newly registered CPT shows 404 because, the register_post_type() doesn't flush the rewrite rules. So it's up to you, whether you want to do it manually or automatically.


Get to /wp-admin/, then Settings » Permalinks, and then just hit the Save Changes button to flush the rewrite rules.


You can flush the rewrite rules using flush_rewrite_rules() function. But as register_post_type() is called in init hook, it will fire every time when the init hook will fire. The same thing the codex is saying also:

This function is useful when used with custom post types as it allows for automatic flushing of the WordPress rewrite rules (usually needs to be done manually for new custom post types). However, this is an expensive operation so it should only be used when absolutely necessary.

That's why it's better to hook the thing to something that fire once, and that flush rules when necessary only. As @cybmeta already showed that to you. But you can follow @bainternet's approach as well:

 * To activate CPT Single page
 * @author  Bainternet
 * @link http://en.bainternet.info/2011/custom-post-type-getting-404-on-permalinks
 * ---
$set = get_option( 'post_type_rules_flased_mycpt' );
if ( $set !== true ){
    flush_rewrite_rules( false );
    update_option( 'post_type_rules_flased_mycpt', true );

He is saving a value to options table only for your post type. And if the value is not there, he's flushing rewrite rules. If it's there, he's not doing it.

But please note, it's actually making a db call every time (if not cached). So, I'd prefer hooking the code after_setup_theme for theme, or register_activation_hook for plugin.


While debugging rewrite rules, plugin like these could be very helpful:

  • Its not newly registered CPT. Also I have tried flushing rewrite rule many time but it didn't worked. When I use "plain" permalink format it works. But not with "Post name" permalink format.
    – Deepak jha
    Mar 7, 2016 at 18:22
  • Could you please confirm that mod_rewrite is enabled on your server and working for other standard URL of that WordPress installation? I'd love to recommend the basic debug process too. Mar 7, 2016 at 18:47
  • On sever I have many WordPress installation with multiple custom post types and all are working good.
    – Deepak jha
    Mar 7, 2016 at 18:57
  • Then it's impossible for us to detect. You can share your product using github, bitbucket, gitlab etc., so that someone can test whether it worked globally or, not. It's too localized to your dev. environment, that nobody can touch about, I'm afraid. :( Mar 7, 2016 at 19:45
  • It was due to a plugin "Remove taxonomy base slug". It was conflicting with base slug of CPT "destinations". I had to use "add_rewrite_rule" to check for slug and manually redirect it to proper location.
    – Deepak jha
    Mar 8, 2016 at 18:10

It was due to a plugin "Remove taxonomy base slug". It was conflicting with base slug of CPT "destinations". I had to use add_rewrite_rule to check for slug and manually redirect it to proper location

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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