Improve SnackBar error message when shown during build (#106658)

diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart
index b5c62ab..f098008 100644
--- a/packages/flutter/lib/src/material/scaffold.dart
+++ b/packages/flutter/lib/src/material/scaffold.dart
@@ -242,7 +242,7 @@
 
   // SNACKBAR API
 
-  /// Shows  a [SnackBar] across all registered [Scaffold]s.
+  /// Shows a [SnackBar] across all registered [Scaffold]s.
   ///
   /// A scaffold can show at most one snack bar at a time. If this function is
   /// called while another snack bar is already visible, the given snack bar
@@ -289,10 +289,43 @@
         },
       null, // SnackBar doesn't use a builder function so setState() wouldn't rebuild it
     );
-    setState(() {
-      _snackBars.addLast(controller);
-    });
-    _updateScaffolds();
+    try {
+      setState(() {
+        _snackBars.addLast(controller);
+      });
+      _updateScaffolds();
+    } catch (exception) {
+      assert (() {
+        if (exception is FlutterError) {
+          final String summary = exception.diagnostics.first.toDescription();
+          if (summary == 'setState() or markNeedsBuild() called during build.') {
+            final List<DiagnosticsNode> information = <DiagnosticsNode>[
+              ErrorSummary('The showSnackBar() method cannot be called during build.'),
+              ErrorDescription(
+                'The showSnackBar() method was called during build, which is '
+                'prohibited as showing snack bars requires updating state. Updating '
+                'state is not possible during build.',
+              ),
+              ErrorHint(
+                'Instead of calling showSnackBar() during build, call it directly '
+                'in your on tap (and related) callbacks. If you need to immediately '
+                'show a snack bar, make the call in initState() or '
+                'didChangeDependencies() instead. Otherwise, you can also schedule a '
+                'post-frame callback using SchedulerBinding.addPostFrameCallback to '
+                'show the snack bar after the current frame.',
+              ),
+              context.describeOwnershipChain(
+                'The ownership chain for the particular ScaffoldMessenger is',
+              ),
+            ];
+            throw FlutterError.fromParts(information);
+          }
+        }
+        return true;
+      }());
+      rethrow;
+    }
+
     return controller;
   }
 
diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart
index d39ce30..370649b 100644
--- a/packages/flutter/test/material/scaffold_test.dart
+++ b/packages/flutter/test/material/scaffold_test.dart
@@ -2582,6 +2582,23 @@
     expect(isDrawerOpen, false);
     expect(isEndDrawerOpen, false);
   });
+
+  testWidgets('ScaffoldMessenger showSnackBar throws an intuitive error message if called during build', (WidgetTester tester) async {
+    await tester.pumpWidget(MaterialApp(
+      home: Scaffold(
+        body: Builder(
+          builder: (BuildContext context) {
+            ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('SnackBar')));
+            return const SizedBox.shrink();
+          },
+        ),
+      ),
+    ));
+
+    final FlutterError error = tester.takeException() as FlutterError;
+    final ErrorSummary summary = error.diagnostics.first as ErrorSummary;
+    expect(summary.toString(), 'The showSnackBar() method cannot be called during build.');
+  });
 }
 
 class _GeometryListener extends StatefulWidget {