Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type 'Null' is not a subtype of type 'String' #53700

Closed
jeremielodi opened this issue Oct 8, 2023 · 14 comments
Closed

type 'Null' is not a subtype of type 'String' #53700

jeremielodi opened this issue Oct 8, 2023 · 14 comments
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. needs-info We need additional information from the issue author (auto-closed after 14 days if no response) P2 A bug or feature request we're likely to work on triaged Issue has been triaged by sub team vm-hot-reload

Comments

@jeremielodi
Copy link

jeremielodi commented Oct 8, 2023

I Suggest to have the file name and the line where has error happened. It's very complicated to know directly where to fixe the type when you face this error.

@bwilkerson
Copy link
Member

Which tool are you using when you see this message without any information about where the error happened?

@jeremielodi
Copy link
Author

Screenshot 2023-10-08 at 17 27 23

@jeremielodi
Copy link
Author

Even with android studio or VS code

@bwilkerson
Copy link
Member

I can reproduce the problem in DartPad, but when I run

void main() {
  Map<String, dynamic> map = {"name": "jeremie", "age": 12};
  String sex = map['sex'];
  print(sex);
}

in VSCode, the following output is printed in the Debug Console:

Unhandled exception:
type 'Null' is not a subtype of type 'String'
#0      main (package:test_package/test.dart:3:10)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#2      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

Exited (255).

The stack trace does indicate where the exception was thrown (on the line marked with #0).

I haven't tried to reproduce it in Android Studio, but I'd be surprised if it didn't provide you with the full stack trace.

@bwilkerson
Copy link
Member

@johnpryan

@jeremielodi
Copy link
Author

jeremielodi commented Oct 8, 2023

I think, I didn't reproduce the issue correctly,
This come to me when I try to get data from http response. If the key doesn't exist in the map or the type doesn't much then this error occured.

Screenshot 2023-10-08 at 17 49 14

@bwilkerson bwilkerson added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. vm-hot-reload labels Oct 8, 2023
@bwilkerson
Copy link
Member

Thanks for the additional information.

This is definitely an issue for DartPad, even without hot reload, but it appears to also be an issue for hot reload.

@johnpryan
Copy link
Contributor

I filed this issue for DartPad: dart-lang/dart-pad#2668

@johnpryan
Copy link
Contributor

@bwilkerson Off topic, but do you know why the Flutter SDK prints a different error message in this scenario? Here's what is printed when the exception is thrown from a Flutter app:

The following TypeErrorImpl was thrown while handling a gesture:
Expected a value of type 'String', but got one of type 'Null'

And here's what the exception looks like if you use a Dart SDK:

type 'Null' is not a subtype of type 'String'

@bwilkerson
Copy link
Member

No, I don't know why they're different. Obviously Flutter is catching the exception at some point and wrapping the message, but I would have expected the second line of Flutter's message to match what the Dart SDK is producing.

Is it possible that you're using two different versions of the Dart SDK somehow? If not, I have no clue.

@johnpryan
Copy link
Contributor

johnpryan commented Oct 10, 2023

@jeremielodi Can you share a small snippet that reproduces the issue? I can't reproduce this issue in Flutter after hot-reloading. I put the code you shared in the _incrementCounter() function in the Counter app and I'm seeing a correct looking error message:

Snippet
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),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    Map<String, dynamic> map = {"name": "jeremie", "age": 12};
    String sex = map['sex'];
    print(sex);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
======== Exception caught by gesture ===============================================================
The following _TypeError was thrown while handling a gesture:
type 'Null' is not a subtype of type 'String'

When the exception was thrown, this was the stack: 
#0      _MyHomePageState._incrementCounter (package:foo/main.dart:37:12)
#1      _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1154:21)
#2      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:275:24)
#3      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:654:11)
#4      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:311:5)
#5      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:244:7)
#6      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:630:9)
#7      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#8      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#9      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#10     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#11     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#12     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:488:19)
#13     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:468:22)
#14     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:333:11)
#15     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:413:7)
#16     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:376:5)
#17     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:323:7)
#18     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:292:9)
#19     _invoke1 (dart:ui/hooks.dart:186:13)
#20     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:424:7)
#21     _dispatchPointerDataPacket (dart:ui/hooks.dart:119:31)
Handler: "onTap"
Recognizer: TapGestureRecognizer#e9d5f
  debugOwner: GestureDetector
  state: possible
  won arena
  finalPosition: Offset(773.1, 562.9)
  finalLocalPosition: Offset(45.1, 34.9)
  button: 1
  sent tap down
====================================================================================================

@a-siva a-siva added P2 A bug or feature request we're likely to work on triaged Issue has been triaged by sub team labels Oct 12, 2023
@a-siva a-siva added the needs-info We need additional information from the issue author (auto-closed after 14 days if no response) label Nov 20, 2023
Copy link

github-actions bot commented Dec 5, 2023

Without additional information we're not able to resolve this issue. Feel free to add more info or respond to any questions above and we can reopen the case. Thanks for your contribution!

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Dec 5, 2023
@eernstg
Copy link
Member

eernstg commented Dec 5, 2023

I guess the real topic here is the lack of stack traces and other information. However, it's worth noting that the example is working as intended:

void main() {
  Map<String, dynamic> map = {"name": "jeremie", "age": 12};
  String sex = map['sex']; // Throws.
  print(sex);
}

The exception is thrown when the line with the comment is reached because the type of the expression map['sex'] is dynamic, and expressions with that type are subject to type checks at run time. The value of an expression of type dynamic can be assigned to anything, but it will be checked at run time that the given value has the required type, in this case it must be a String. However, the value is actually null. So the dynamic type check fails and an exception is thrown.

Nothing surprising about this, and everything is working as intended.

However, if you wish to avoid this kind of dynamic type check then you can make sure that you have an 'analysis_options.yaml' file in the root of your package that contains at least the following:

analyzer:
  language:
    strict-casts: true

You'll find some extra information about these settings here.

@a-balakmet
Copy link

a-balakmet commented Mar 6, 2024

I had the same exception with code below:

class Place { final int id; final String name; final String? address; }
I solved it like this:

class Place { final int id; final String name; final dynamic address; }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. needs-info We need additional information from the issue author (auto-closed after 14 days if no response) P2 A bug or feature request we're likely to work on triaged Issue has been triaged by sub team vm-hot-reload
Projects
None yet
Development

No branches or pull requests

6 participants