I know you already find the solution, because you figured out this question was already asked and answered…
However, once this question is a bounty one and cannot be closed as duplicate, I want to make sense to this, and add (a bit of) additional value on the answers already posted.
What is done in those answers (the one by @RachelCarden and the one posted here by @matthew-boynes) is what you need, but it is hardcoded, i.e. you have to manually add the cpt archive slug in the filter function.
What I want to obtain is a filter that works in the same way, but dinamically, something like:
add_filter('wp_unique_post_slug_is_bad_hierarchical_slug', 'prevent_slug_override', 99, 3);
add_filter('wp_unique_post_slug_is_bad_flat_slug', 'prevent_slug_override', 99, 3);
function prevent_slug_override( $now, $slug, $type ) {
if ( in_array($type, array('nav_menu_item', 'revision', 'attachment') ) )
return $now;
$cpts = get_post_types( array('_builtin' => false), 'objects' );
$check_bad = array();
foreach ( $cpts as $cpt => $object ) {
if ( $object->has_archive ) {
if (
! empty($object->rewrite) && isset($object->rewrite['slug']) &&
! empty($object->rewrite['slug']) && ($object->rewrite['slug'] != $cpt)
) {
$check_bad[] = $object->rewrite['slug'];
} else {
$check_bad[] = is_string($object->has_archive) ? $object->has_archive : $cpt;
}
}
}
if ( in_array($slug, $check_bad) ) return true;
return $now;
}