free geoip
27

Error Handling with HTTP Requests in Dart

When building mobile or web applications with Dart—especially using the Flutter framework—making HTTP requests to REST APIs is a routine…

When building mobile or web applications with Dart—especially using the Flutter framework—making HTTP requests to REST APIs is a routine task. However, handling errors effectively during these operations is essential for creating reliable and user-friendly applications. In this guide, you’ll learn how to manage HTTP errors properly in Dart using the http package, covering timeout handling, client/server-side error responses, and exception types.

Error Handling with HTTP Requests in Dart

Why Error Handling Matters

Without proper error handling, your app might crash or behave unexpectedly when the API is down, the user has no internet connection, or the server returns a 500 error. Proper error handling ensures your application fails gracefully and provides helpful feedback to the user.

Installing the HTTP Package

Make sure you have the http package added in your pubspec.yaml:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
dependencies:
http: ^0.13.6
dependencies: http: ^0.13.6
dependencies:
  http: ^0.13.6

Making HTTP Requests with Error Handling

Here is a complete example that includes:

  • HTTP GET request
  • Timeout exception
  • Socket exception
  • HTTP status code validation
File: api_service.dart
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
class ApiService {
final String baseUrl = 'https://jsonplaceholder.typicode.com';
Future<dynamic> fetchData(String endpoint) async {
final url = Uri.parse('$baseUrl/$endpoint');
try {
final response = await http.get(url).timeout(const Duration(seconds: 10));
if (response.statusCode >= 200 && response.statusCode < 300) {
return jsonDecode(response.body);
} else {
throw HttpException('Server responded with status: ${response.statusCode}');
}
} on SocketException {
throw Exception('No Internet connection.');
} on HttpException catch (e) {
throw Exception('HTTP error: ${e.message}');
} on FormatException {
throw Exception('Bad response format.');
} on TimeoutException {
throw Exception('The connection has timed out.');
}
}
}
import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; class ApiService { final String baseUrl = 'https://jsonplaceholder.typicode.com'; Future<dynamic> fetchData(String endpoint) async { final url = Uri.parse('$baseUrl/$endpoint'); try { final response = await http.get(url).timeout(const Duration(seconds: 10)); if (response.statusCode >= 200 && response.statusCode < 300) { return jsonDecode(response.body); } else { throw HttpException('Server responded with status: ${response.statusCode}'); } } on SocketException { throw Exception('No Internet connection.'); } on HttpException catch (e) { throw Exception('HTTP error: ${e.message}'); } on FormatException { throw Exception('Bad response format.'); } on TimeoutException { throw Exception('The connection has timed out.'); } } }
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

class ApiService {
  final String baseUrl = 'https://jsonplaceholder.typicode.com';

  Future<dynamic> fetchData(String endpoint) async {
    final url = Uri.parse('$baseUrl/$endpoint');

    try {
      final response = await http.get(url).timeout(const Duration(seconds: 10));

      if (response.statusCode >= 200 && response.statusCode < 300) {
        return jsonDecode(response.body);
      } else {
        throw HttpException('Server responded with status: ${response.statusCode}');
      }
    } on SocketException {
      throw Exception('No Internet connection.');
    } on HttpException catch (e) {
      throw Exception('HTTP error: ${e.message}');
    } on FormatException {
      throw Exception('Bad response format.');
    } on TimeoutException {
      throw Exception('The connection has timed out.');
    }
  }
}

File: main.dart

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import 'package:flutter/material.dart';
import 'api_service.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends <a href="https://aliendro.id/create-ui-with-statelesswidget-in-dart/">StatelessWidget</a> {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'HTTP Error Handling Demo',
home: Scaffold(
appBar: AppBar(title: const Text('API Error Handling')),
body: const Center(child: DataDisplay()),
),
);
}
}
class DataDisplay extends <a href="https://aliendro.id/statefulwidget-vs-statelesswidget-in-dart-guide/">StatefulWidget</a> {
const DataDisplay({super.key});
@override
State<DataDisplay> createState() => _DataDisplayState();
}
class _DataDisplayState extends State<DataDisplay> {
final ApiService _apiService = ApiService();
String _result = 'Fetching data...';
@override
void initState() {
super.initState();
_loadData();
}
void _loadData() async {
try {
final data = await _apiService.fetchData('posts/1');
setState(() {
_result = data.toString();
});
} catch (e) {
setState(() {
_result = 'Error: $e';
});
}
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text(_result),
);
}
}
import 'package:flutter/material.dart'; import 'api_service.dart'; void main() { runApp(const MyApp()); } class MyApp extends <a href="https://aliendro.id/create-ui-with-statelesswidget-in-dart/">StatelessWidget</a> { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'HTTP Error Handling Demo', home: Scaffold( appBar: AppBar(title: const Text('API Error Handling')), body: const Center(child: DataDisplay()), ), ); } } class DataDisplay extends <a href="https://aliendro.id/statefulwidget-vs-statelesswidget-in-dart-guide/">StatefulWidget</a> { const DataDisplay({super.key}); @override State<DataDisplay> createState() => _DataDisplayState(); } class _DataDisplayState extends State<DataDisplay> { final ApiService _apiService = ApiService(); String _result = 'Fetching data...'; @override void initState() { super.initState(); _loadData(); } void _loadData() async { try { final data = await _apiService.fetchData('posts/1'); setState(() { _result = data.toString(); }); } catch (e) { setState(() { _result = 'Error: $e'; }); } } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), child: Text(_result), ); } }
import 'package:flutter/material.dart';
import 'api_service.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'HTTP Error Handling Demo',
      home: Scaffold(
        appBar: AppBar(title: const Text('API Error Handling')),
        body: const Center(child: DataDisplay()),
      ),
    );
  }
}

class DataDisplay extends StatefulWidget {
  const DataDisplay({super.key});

  @override
  State<DataDisplay> createState() => _DataDisplayState();
}

class _DataDisplayState extends State<DataDisplay> {
  final ApiService _apiService = ApiService();
  String _result = 'Fetching data...';

  @override
  void initState() {
    super.initState();
    _loadData();
  }

  void _loadData() async {
    try {
      final data = await _apiService.fetchData('posts/1');
      setState(() {
        _result = data.toString();
      });
    } catch (e) {
      setState(() {
        _result = 'Error: $e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Text(_result),
    );
  }
}

This code provides a robust and reusable pattern for HTTP requests in Dart, catching various error scenarios cleanly.

To deepen your understanding of HTTP error codes and best practices in API response management, check out this MDN Web Docs guide.

rysasahrial

Leave a Reply

Your email address will not be published. Required fields are marked *