The Problem

When WordPress multisite is configured in subdirectory mode (e.g., example.com/site2/), the .htaccess rewrite rules can conflict with existing rules, custom post types, or other plugins, causing 404 errors on subsites.

Symptoms

  • Subsites return 404 errors
  • Subsite admin dashboard loads but frontend is broken
  • Main site works but subsites do not
  • Custom post type URLs return 404 on subsites
  • Media files on subsites return 404

Real Error

bash
https://example.com/site2/about/ -> 404 Not Found
https://example.com/site2/wp-admin/ -> Works fine

The Correct Multisite Subdirectory .htaccess

```apache RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index\.php$ - [L]

# Uploaded files RewriteRule ^([_0-9a-zA-Z-]+/)?files/(.+) wp-includes/ms-files.php?file=$2 [L]

# Add a trailing slash to /wp-admin RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ - [L] RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L] RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L] RewriteRule . index.php [L] ```

How to Fix It

Fix 1: Replace .htaccess with Correct Rules

```bash # Backup existing .htaccess cp .htaccess .htaccess.backup

# Replace with WordPress multisite subdirectory rules # (see the correct rules above) ```

Fix 2: Regenerate .htaccess via WP-CLI

```bash # Flush rewrite rules for all sites wp rewrite flush --hard --network

# Or per site wp site list --field=url | while read url; do wp rewrite flush --hard --url=$url done ```

Fix 3: Fix Custom Post Type Permalinks on Subsites

php
// functions.php (network-activated mu-plugin)
function fix_multisite_cpt_rewrite($post_type, $args) {
  // Ensure CPT rewrite rules work on subsites
  $args['rewrite'] = array_merge((array)$args['rewrite'], [
    'with_front' => false  // Do not prepend site subdirectory
  ]);
  return $args;
}

Fix 4: Nginx Multisite Subdirectory Configuration

```nginx server { server_name example.com; root /var/www/html; index index.php;

# Multisite subdirectory rules location / { try_files $uri $uri/ /index.php?$args; }

# Handle subsite paths rewrite ^/([_0-9a-zA-Z-]+/)?wp-admin$ /$1wp-admin/ permanent;

location ~ ^/([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) { # Allow access to WP files }

location ~ ^/([_0-9a-zA-Z-]+/)?(.*\.php)$ { fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$2; include fastcgi_params; }

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ { expires 30d; add_header Cache-Control "public, immutable"; } } ```

Fix 5: Verify Subsite Configuration

```bash # List all subsites wp site list

# Check a specific subsite's URL wp option get home --url=https://example.com/site2 wp option get siteurl --url=https://example.com/site2

# Both should return https://example.com/site2 ```

Fix 6: Fix Media URLs on Subsites

php
// mu-plugin for multisite media
add_filter('upload_dir', function($uploads) {
  // Fix media path for subdirectory multisite
  $uploads['url'] = str_replace('/wp-content/uploads', '/site2/wp-content/uploads', $uploads['url']);
  return $uploads;
});