I’m running into a strange TLS/HTTPS issue in my Flutter project and can’t figure out why it only happens inside Flutter/Dart.
I have a backend API hosted at:
https://my-backend/api/v1 If I call the endpoint from Postman or curl, it works correctly:
curl -X GET \ 'https://my-backend/api/v1/users/123' However, when I try to call the exact same URL from Flutter (or even a simple Dart test), I get this error:
HandshakeException: Handshake error in client (OS Error: WRONG_VERSION_NUMBER(tls_record.cc:127)) Code that generates the error
test('should fetch user by id', () async { final testBaseUri = BaseUri( baseUrl: 'https://my-backend/api/v1', ); final userResult = await users_res.getUserById( '123', testBaseUri, ); expect(userResult, isNotNull); }); getUserById:
final url = baseUri.getEndpoint('/users/$id'); final defaultHeaders = { 'Accept': 'application/json', 'Content-Type': 'application/json', }; final response = await backendClient.get(url, headers: defaultHeaders); if (response.statusCode >= 200 && response.statusCode < 300) { return User.fromJson(json.decode(response.body)); } else { throw Exception('Failed to get user: ${response.reasonPhrase}'); } HTTP client:
final backendClient = http.Client(); The generated URL:
https://my-backend/api/v1/users/123 So it’s definitely calling the correct route.
What I’ve already checked/tried • Verified that the backend does serve HTTPS (confirmed via curl/Postman). • Verified the generated URL is correct.
• Tried using http.get(Uri.parse(...)) directly — same error. • Tried from both Flutter tests and a raw Dart script — still the same error. • Tried disabling proxy usage via:
HttpClient()..findProxy = (_) => 'DIRECT'; • Tried an insecure client with badCertificateCallback (referenced from here )— the handshake error still happens. • No custom HttpOverrides.global in my code. • Tested on different networks.
The backend is reachable from everything except Dart/Flutter’s HTTP client, which fails immediately during TLS handshake before even sending a request.
My question
What could cause Dart/Flutter’s HttpClient to fail the TLS handshake with WRONG_VERSION_NUMBER while Postman and curl work fine with the exact same HTTPS URL?
Is there something environment-specific about Flutter/Dart TLS behavior that I may be missing (proxy, DNS, certificate chain, ALPN, etc.)?
Any guidance on how to debug this further is appreciated.