After creating a React Native app and uploading an image, PDF, video, or document on Android, you may suddenly see `TypeError: Network request failed` or `AxiosError: Network Error`. This error is confusing because the same API may work correctly on iOS, Postman, or the browser. In most cases, the issue is not the backend itself - it is caused by incorrect FormData headers, Axios defaults, Android emulator localhost issues, cleartext HTTP restrictions, or an invalid file object.
The Error
What Causes This Error
React Native Android handles file uploads differently from browser JavaScript. When FormData is used with the wrong `Content-Type`, missing file fields, blocked HTTP traffic, or a wrong local API URL, Android may fail before the request reaches your backend. That is why your server logs may show nothing even though the app displays a network error.
- Manually setting `Content-Type: multipart/form-data` without a boundary
- Axios sending `application/x-www-form-urlencoded` for a FormData request
- Missing `uri`, `type`, or `name` in the uploaded file object
- Using `localhost` instead of `10.0.2.2` on Android emulator
- Using HTTP instead of HTTPS on newer Android versions
- Invalid file URI returned from image picker or document picker
- Backend upload endpoint not accepting multipart form data
Fix 1: Use Correct FormData File Object
React Native FormData needs a proper file object. Always pass `uri`, `type`, and `name` when appending a file. If any of these values are missing, Android can fail while creating the multipart request.
Fix 2: Do Not Set Content-Type Manually With Fetch
When using `fetch`, do not manually add `Content-Type: multipart/form-data`. React Native needs to generate the multipart boundary automatically. If you set the header yourself, Android may receive an incomplete multipart request and throw a network error.
Fix 3: Remove Wrong Axios Content-Type
Axios can sometimes send the wrong default `Content-Type` for React Native FormData uploads. If Axios sends `application/x-www-form-urlencoded`, Android may throw a multipart error. The safest fix is to stop Axios from transforming the request and avoid manually forcing multipart headers.
Fix 4: Check Android Emulator Localhost
If your API is running locally, Android emulator cannot access your computer using `localhost`. Inside the emulator, `localhost` points to the emulator itself. Use `10.0.2.2` to access a backend running on your development machine.
Fix 5: Use HTTPS or Allow Cleartext in Development
Newer Android versions block cleartext HTTP traffic by default. For production apps, use HTTPS. For local development only, you can temporarily allow cleartext traffic in `AndroidManifest.xml`.
Fix 6: Normalize File URI From Picker
Image picker and document picker libraries can return different URI formats such as `file://`, `content://`, or cached paths. Before uploading, normalize the selected file and provide a fallback MIME type and filename.
Quick Diagnosis Checklist
- Check if the request reaches backend logs
- Test the same API with Postman
- Confirm the file object has `uri`, `type`, and `name`
- Remove manual `Content-Type` from fetch requests
- Fix Axios so it does not send `application/x-www-form-urlencoded`
- Use `10.0.2.2` instead of `localhost` on Android emulator
- Use HTTPS or enable cleartext only for development
- Test upload on both emulator and real Android device
FAQ
Why does upload work on iOS but fail on Android?
Android networking is stricter with multipart headers, file URIs, and HTTP security rules. A request that works on iOS can still fail on Android if headers or file values are incorrect.
Should I manually set `Content-Type: multipart/form-data`?
Usually no. Let React Native generate the multipart boundary automatically. Manually setting this header is one of the most common causes of Android upload failure.
Why does Axios fail with FormData in React Native Android?
Axios may send an incorrect default content type for FormData requests. Prevent Axios from transforming the body and avoid forcing the wrong header.
Why does localhost not work on Android emulator?
`localhost` inside the Android emulator points to the emulator itself, not your computer. Use `10.0.2.2` when your backend is running on your development machine.
Is this always a backend issue?
No. If the request does not appear in backend logs, the problem is usually inside React Native Android networking, file URI handling, local URL setup, or Android HTTP security configuration.