-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Description
Steps to Reproduce:
An unexpected behavior occurs with Flutter compiled to WebAssembly (wasm
) when using a switch-case
on a nullable type (case null
). Specifically, this happens when comparing a nullable String?
simultaneously with a constant string and null
. The issue occurs only in production mode compiled to WebAssembly (flutter build web --wasm
), but not in JavaScript builds (flutter build web
) or debug mode.
-
Use the provided sample code directly.
-
Compile the Flutter application to WebAssembly:
flutter build web --wasm
-
Host the generated
build/web
files locally (e.g., using a Python HTTP server). -
Observe the issue:
- The
switch-case
unexpectedly falls into thedefault
case, even when the value matches the expected constant (kTypeString
) or explicitlynull
.
- The
Additional Information:
-
Compilation: WebAssembly (
flutter build web --wasm
) -
Does NOT reproduce with:
- Debug mode (
flutter run
) - JavaScript build (
flutter build web
)
- Debug mode (
-
Hosting environment tested: Local Python HTTP server and Azure Static Web Apps.
Additionally, I attempted reproducing by directly assigning the DTO in code (without fetching from backend), but in this scenario, the issue did not occur.
For convenience, I've hosted an API endpoint that returns the required DTO, which can be used to reproduce the issue directly.
Expected results
The nullable string comparison should correctly identify the case where the value matches the provided constant (kTypeString
) or explicitly null
, thus executing the correct case logic.
Actual results
The comparison falls into the default
case unexpectedly, indicating an incorrect type matching in the wasm build:
Unexpected type on SWITCH CASE: PhotographicBox | PhotographicBox
Code sample
Code sample
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
home: const MyHomePage(title: 'Flutter Switch Case Error Example'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
const kTypeString = 'PhotographicBox';
class _MyHomePageState extends State<MyHomePage> {
String? _option;
String? get type => _option;
@override
void initState() {
super.initState();
load();
}
Future<void> load() async {
final response = await Dio().get(
'https://photune-dev-dmbmhkh7ehedf0fk.brazilsouth-01.azurewebsites.net/v1/tests/flutter-error',
);
setState(() {
_option = (response.data as Map<String, dynamic>)['type'] as String?;
});
}
String get infoSwitchCase {
switch (type) {
case kTypeString:
return 'It Works! on SWITCH CASE';
case null:
return 'Type is null on SWITCH CASE';
default:
return 'Unexpected type on SWITCH CASE: $type | $kTypeString';
}
}
String get infoSwitchCaseWithoutNull {
switch (type) {
case kTypeString:
return 'It Works! on SWITCH CASE WITHOUT NULL';
default:
return 'Unexpected type on SWITCH CASE WITHOUT NULL: $type | $kTypeString';
}
}
String get infoSwitchExpression {
return switch (type) {
kTypeString => 'It Works with SWITCH EXPRESSION',
null => 'Type is null with SWITCH EXPRESSION',
_ => 'Unexpected type with SWITCH EXPRESSION: $type | $kTypeString',
};
}
String get infoIfCase {
if (type case kTypeString) {
return 'It Works with IF CASE';
} else if (type case null) {
return 'Type is null with IF CASE';
} else {
return 'Unexpected type with IF CASE: $type | $kTypeString';
}
}
String get infoIfEquals {
if (type == kTypeString) {
return 'It Works with IF';
} else if (type == null) {
return 'Type is null with IF';
} else {
return 'Unexpected type with IF: $type | $kTypeString';
}
}
@override
Widget build(BuildContext context) {
if (_option == null) {
return Scaffold(
appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
body: const Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildText(infoIfEquals),
const SizedBox(height: 16),
_buildText(infoIfCase),
const SizedBox(height: 16),
_buildText(infoSwitchExpression),
const SizedBox(height: 16),
_buildText(infoSwitchCase),
const SizedBox(height: 16),
_buildText(infoSwitchCaseWithoutNull),
const SizedBox(height: 16),
],
),
);
}
Widget _buildText(String text) {
return Text(
text,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(color: text.startsWith('It Works') ? null : Colors.red),
);
}
}
My pubspec.yaml
name: teste_flutter
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: ^3.8.1
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
dio: ^5.8.0+1
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^5.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/to/asset-from-package
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/to/font-from-package
Screenshots or Video
Logs
Logs
Flutter Doctor output
Doctor output
[√] Flutter (Channel stable, 3.32.5, on Microsoft Windows [versÆo 10.0.26100.4484], locale pt-BR) [432ms]
• Flutter version 3.32.5 on channel stable at C:\Users\jeferson\flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision fcf2c11572 (2 weeks ago), 2025-06-24 11:44:07 -0700
• Engine revision dd93de6fb1
• Dart version 3.8.1
• DevTools version 2.45.1
[√] Windows Version (11 Enterprise 64-bit, 24H2, 2009) [3,0s]
[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [5,4s]
• Android SDK at D:\_AndroidStudioConfig\Sdk
• Platform android-34, build-tools 34.0.0
• Java binary at: C:\Program Files\Android\Android Studio1\jbr\bin\java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
• All Android licenses accepted.
[√] Chrome - develop for the web [115ms]
• CHROME_EXECUTABLE = C:\Program Files\Google\Chrome\Application\chrome.exe
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.14.8) [115ms]
• Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
• Visual Studio Community 2022 version 17.14.36301.6
• Windows 10 SDK version 10.0.26100.0
[√] Android Studio (version 2025.1.1) [24ms]
• Android Studio at C:\Program Files\Android\Android Studio1
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
[√] VS Code, 64-bit edition (version 1.99.3) [22ms]
• VS Code at C:\Program Files\Microsoft VS Code
• Flutter extension version 3.114.0
[√] Connected device (3 available) [202ms]
• Windows (desktop) • windows • windows-x64 • Microsoft Windows [versÆo 10.0.26100.4484]
• Chrome (web) • chrome • web-javascript • Google Chrome 138.0.7204.97
• Edge (web) • edge • web-javascript • Microsoft Edge 138.0.3351.65
[√] Network resources [755ms]
• All expected network resources are available.
• No issues found!