Catching Errors With try
Part of the Data and the Network section of Coddy's Flutter journey. Lesson 10 of 27.
A network call can fail: the phone has no signal, the server is down, the path is wrong. When fetch fails, it throws an error: an ApiException, a small class at the top of api.dart with a statusCode and a message. An error nobody catches stops your function and shows up as a red error in the Console, and the person sees a spinner that never ends.
Catch it with try and catch:
try {
final text = await fetch('/message');
// only runs when fetch worked
} catch (e) {
// only runs when fetch threw
print('It failed: $e');
}Dart runs the try block. If anything in it throws, Dart jumps straight to catch, and e holds the error. The lines after the failing one in try never run.
Put the await itself inside try: that is the line that throws. Then show the person what happened, in words, instead of crashing.
To see it fail in the preview, write offline = true; as the first line of main and press Run. offline comes from api.dart: it makes every call fail as if the phone had no signal. Take the line out before you press Check.
Challenge
MediumMake loadMessage survive a failed call:
- put the
fetchand thesetStateafter it in atryblock - in
catch (e), stop the spinner and set the message toCould not load: $e
Try it yourself
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: MessageScreen(),
);
}
}
class MessageScreen extends StatefulWidget {
const MessageScreen({super.key});
@override
State<MessageScreen> createState() => _MessageScreenState();
}
class _MessageScreenState extends State<MessageScreen> {
String message = 'No message yet';
bool loading = false;
Future<void> loadMessage() async {
setState(() {
loading = true;
});
final text = await fetch('/message');
setState(() {
message = text;
loading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
loading
? const CircularProgressIndicator()
: Text(message, style: const TextStyle(fontSize: 24)),
const SizedBox(height: 24),
ElevatedButton(onPressed: loadMessage, child: const Text('Load message')),
],
),
),
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Data and the Network
3When Calls Fail
Catching Errors With tryThrowing an ErrorCleaning Up With finallyThe FutureBuilder Error StateA Try Again ButtonPractice on your own: Online Flutter compiler