diff --git src/wp-admin/includes/upgrade.php src/wp-admin/includes/upgrade.php
index 558b88e..e846bce 100644
--- src/wp-admin/includes/upgrade.php
+++ src/wp-admin/includes/upgrade.php
@@ -1363,6 +1363,12 @@ function upgrade_network() {
 			update_site_option( 'illegal_names', $illegal_names );
 		}
 	}
+
+	// 4.0.0
+	if ( $wp_current_db_version < 30000 ) {
+		$wpdb->update( $wpdb->blogs, array( 'path' => '/' ), array( 'path' => '' ) );
+	}
+
 }
 
 // The functions we use to actually do stuff
diff --git src/wp-includes/ms-blogs.php src/wp-includes/ms-blogs.php
index 16a4918..46e36e8 100644
--- src/wp-includes/ms-blogs.php
+++ src/wp-includes/ms-blogs.php
@@ -290,6 +290,11 @@ function update_blog_details( $blog_id, $details = array() ) {
 	$details = array_merge($current_details, $details);
 	$details['last_updated'] = current_time('mysql', true);
 
+	// Ensure that the path always has a slash
+	if ( isset( $details['path'] ) ) {
+		$details['path'] = trailingslashit( $details['path'] );
+	}
+
 	$update_details = array();
 	$fields = array( 'site_id', 'domain', 'path', 'registered', 'last_updated', 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id');
 	foreach ( array_intersect( array_keys( $details ), $fields ) as $field )
diff --git src/wp-includes/ms-load.php src/wp-includes/ms-load.php
index 02224bd..95db548 100644
--- src/wp-includes/ms-load.php
+++ src/wp-includes/ms-load.php
@@ -374,6 +374,11 @@ function get_site_by_path( $domain, $path, $segments = null ) {
 		$site = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s AND path = %s", $domains[0], $paths[0] ) );
 	}
 
+	// One last attempt, in case the path column is empty for the site. Addresses #28273
+	if ( ! $site ) {
+		$site = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->blogs WHERE domain = %s AND path = ''", $domains[0] ) );
+	}
+
 	if ( $site ) {
 		// @todo get_blog_details()
 		return $site;
