Index: src/wp-admin/includes/template.php
===================================================================
--- src/wp-admin/includes/template.php	(revision 38683)
+++ src/wp-admin/includes/template.php	(working copy)
@@ -1394,6 +1394,7 @@
  * action hook).
  *
  * @since 3.0.0
+ * @since 4.7.0 The function now supports getting network settings errors from a transient.
  *
  * @global array $wp_settings_errors Storage array of errors registered during this pageload
  *
@@ -1412,10 +1413,13 @@
 	if ( $sanitize )
 		sanitize_option( $setting, get_option( $setting ) );
 
-	// If settings were passed back from options.php then use them.
+	// If settings were passed back from options.php or network/settings.php then use them.
 	if ( isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] && get_transient( 'settings_errors' ) ) {
 		$wp_settings_errors = array_merge( (array) $wp_settings_errors, get_transient( 'settings_errors' ) );
 		delete_transient( 'settings_errors' );
+	} elseif ( is_network_admin() && isset( $_GET['updated'] ) && $_GET['updated'] && get_site_transient( 'settings_errors' ) ) {
+		$wp_settings_errors = array_merge( (array) $wp_settings_errors, get_site_transient( 'settings_errors' ) );
+		delete_site_transient( 'settings_errors' );
 	}
 
 	// Check global in case errors have been added on this pageload.
Index: src/wp-admin/network/settings.php
===================================================================
--- src/wp-admin/network/settings.php	(revision 38683)
+++ src/wp-admin/network/settings.php	(working copy)
@@ -84,6 +84,13 @@
 	 */
 	do_action( 'update_wpmu_options' );
 
+	// If no settings errors were registered, add a general 'updated' message.
+	if ( ! count( get_settings_errors() ) ) {
+		add_settings_error( 'general', 'settings_updated', __( 'Settings saved.' ), 'updated' );
+	}
+
+	set_site_transient( 'settings_errors', get_settings_errors(), 30 );
+
 	wp_redirect( add_query_arg( 'updated', 'true', network_admin_url( 'settings.php' ) ) );
 	exit();
 }
@@ -91,7 +98,7 @@
 include( ABSPATH . 'wp-admin/admin-header.php' );
 
 if ( isset( $_GET['updated'] ) ) {
-	?><div id="message" class="updated notice is-dismissible"><p><?php _e( 'Settings saved.' ) ?></p></div><?php
+	settings_errors();
 }
 ?>
 
Index: tests/phpunit/tests/admin/includesTemplate.php
===================================================================
--- tests/phpunit/tests/admin/includesTemplate.php	(revision 38683)
+++ tests/phpunit/tests/admin/includesTemplate.php	(working copy)
@@ -50,7 +50,7 @@
 		global $wp_meta_boxes;
 
 		add_meta_box( 'testbox1', 'Test Metabox', '__return_false', 'post' );
-		
+
 		$this->assertArrayHasKey( 'testbox1', $wp_meta_boxes['post']['advanced']['default'] );
 	}
 
@@ -79,7 +79,7 @@
 		// Add a meta box to three different post types
 		add_meta_box( 'testbox1', 'Test Metabox', '__return_false', array( 'post', 'comment', 'attachment' ) );
 
-		$this->assertArrayHasKey( 'testbox1', $wp_meta_boxes['post']['advanced']['default'] ); 
+		$this->assertArrayHasKey( 'testbox1', $wp_meta_boxes['post']['advanced']['default'] );
 		$this->assertArrayHasKey( 'testbox1', $wp_meta_boxes['comment']['advanced']['default'] );
 		$this->assertArrayHasKey( 'testbox1', $wp_meta_boxes['attachment']['advanced']['default'] );
 	}
@@ -108,4 +108,183 @@
 		$this->assertFalse( $wp_meta_boxes['attachment']['advanced']['default']['testbox1'] );
 	}
 
-}
\ No newline at end of file
+	/**
+	 * @ticket 18088
+	 */
+	public function test_get_settings_errors_all_error_codes() {
+		global $wp_settings_errors;
+
+		$_orig_settings_errors = $wp_settings_errors;
+
+		$wp_settings_errors = array();
+
+		$foo_codes = range( 0, 4 );
+		$bar_codes = range( 13, 16 );
+
+		foreach ( $foo_codes as $foo_code ) {
+			$wp_settings_errors[] = array(
+				'setting' => 'foo',
+				'code'    => $foo_code,
+				'message' => 'Foo.',
+				'type'    => 'error',
+			);
+		}
+
+		foreach ( $bar_codes as $bar_code ) {
+			$wp_settings_errors[] = array(
+				'setting' => 'bar',
+				'code'    => $bar_code,
+				'message' => 'Bar.',
+				'type'    => 'error',
+			);
+		}
+
+		$result = get_settings_errors();
+
+		$wp_settings_errors = $_orig_settings_errors;
+
+		$this->assertEquals( array_merge( $foo_codes, $bar_codes ), wp_list_pluck( $result, 'code' ) );
+	}
+
+	/**
+	 * @ticket 18088
+	 */
+	public function test_get_settings_errors_single_error_code() {
+		global $wp_settings_errors;
+
+		$_orig_settings_errors = $wp_settings_errors;
+
+		$wp_settings_errors = array();
+
+		$foo_codes = range( 0, 4 );
+		$bar_codes = range( 13, 16 );
+
+		foreach ( $foo_codes as $foo_code ) {
+			$wp_settings_errors[] = array(
+				'setting' => 'foo',
+				'code'    => $foo_code,
+				'message' => 'Foo.',
+				'type'    => 'error',
+			);
+		}
+
+		foreach ( $bar_codes as $bar_code ) {
+			$wp_settings_errors[] = array(
+				'setting' => 'bar',
+				'code'    => $bar_code,
+				'message' => 'Bar.',
+				'type'    => 'error',
+			);
+		}
+
+		$result = get_settings_errors( 'foo' );
+
+		$wp_settings_errors = $_orig_settings_errors;
+
+		$this->assertEquals( $foo_codes, wp_list_pluck( $result, 'code' ) );
+	}
+
+	/**
+	 * @ticket 18088
+	 */
+	public function test_get_settings_errors_invalid_error_code() {
+		global $wp_settings_errors;
+
+		$_orig_settings_errors = $wp_settings_errors;
+
+		$wp_settings_errors = array();
+
+		$codes = range( 0, 4 );
+
+		foreach ( $codes as $code ) {
+			$wp_settings_errors[] = array(
+				'setting' => 'foo',
+				'code'    => $code,
+				'message' => 'Foo.',
+				'type'    => 'error',
+			);
+		}
+
+		$result = get_settings_errors( 'foobar' );
+
+		$wp_settings_errors = $_orig_settings_errors;
+
+		$this->assertEmpty( $result );
+	}
+
+	/**
+	 * @ticket 18088
+	 */
+	public function test_get_settings_errors_from_transient() {
+		global $wp_settings_errors;
+
+		$_orig_settings_errors = $wp_settings_errors;
+
+		$wp_settings_errors = array();
+
+		$codes = range( 0, 4 );
+
+		$errors = array();
+		foreach ( $codes as $code ) {
+			$errors[] = array(
+				'setting' => 'foo',
+				'code'    => $code,
+				'message' => 'Foo.',
+				'type'    => 'error',
+			);
+		}
+
+		set_transient( 'settings_errors', $errors, 30 );
+
+		$_GET['settings-updated'] = 'true';
+
+		$result = get_settings_errors();
+
+		unset( $_GET['settings-updated'] );
+		$wp_settings_errors = $_orig_settings_errors;
+
+		$this->assertEquals( $codes, wp_list_pluck( $result, 'code' ) );
+	}
+
+	/**
+	 * @ticket 18088
+	 */
+	public function test_get_settings_errors_from_network_transient() {
+		if ( ! is_multisite() ) {
+			$this->markTestSkipped( 'Test only runs in multisite' );
+		}
+
+		global $wp_settings_errors, $current_screen;
+
+		$_orig_settings_errors = $wp_settings_errors;
+		$_orig_screen          = $current_screen;
+
+		$wp_settings_errors = array();
+		$current_screen = WP_Screen::get( 'dashboard-network' );
+
+		$codes = range( 3, 8 );
+
+		$errors = array();
+		foreach ( $codes as $code ) {
+			$errors[] = array(
+				'setting' => 'foo',
+				'code'    => $code,
+				'message' => 'Foo.',
+				'type'    => 'error',
+			);
+		}
+
+		set_site_transient( 'settings_errors', $errors, 30 );
+
+		$_GET['updated'] = 'true';
+
+		$result = get_settings_errors();
+
+		unset( $_GET['updated'] );
+		$wp_settings_errors = $_orig_settings_errors;
+		$current_screen     = $_orig_screen;
+
+		$this->assertEquals( $codes, wp_list_pluck( $result, 'code' ) );
+	}
+
+}
