Notes on learning stage of developing my own React Native education app using Expo Framework - Part 8
- Opened lessons index.tsx while in main branch
- Right-Clicked file tab -> Open Changes -> Open Changes with Branch or Tag -> Selected DummyLogin branch
- located GuestLogin-login.tsx.txt file in 'Comparing dummylogin with main'
- Mouse Hover -> Click Open File at Revision (or even Click entry should work I think but slightly diff UI)
- -> 'GuestLogin\GuestLogin-login.tsx.txt (main)' is the title of file tab
- File shows contents of GuestLogin-login.tsx.txt in main branch
- Copy file contents to clipboard
“Uncaught error: 6000ms timeout exceeded”
almost always comes from React Native Web / Expo Router / React Query / Clerk / networking timeouts in development, not from your app logic.
Here are the most likely sources — all based on your project history:
✅ 1. React Query dev mode timeout
React Query has a default 5–6 second timeout for some dev tools and background retries.
If any request takes too long (slow emulator network), React Query DevTools can throw:
timeout exceeded (6000 ms)
These do NOT appear in Metro because React Query throws them internally before logging.
This is the number one cause.
✅ 2. Clerk dev session check timeout
Clerk sometimes triggers:
Uncaught Error: timeout exceeded
when:
-
emulator network is slow
-
you have dummylogin logic
-
app checks for Clerk session but reaches 6s timeout
Your app continues fine after dismissing because Clerk retries quietly.
✅ 3. Expo Router preloading timeout
Expo Router preloads screens in the background (default 6000ms).
If a route takes too long to load during dev:
Route preload timed out after 6000ms
This matches what you saw: only in debug, disappears in release.
✅ 4. Network fetch (API) dev timeout
Some libraries (Axios, fetch wrappers, backend SDKs) have a default timeout of 6000 ms in dev mode.
Even if your code doesn’t set a timeout, some libraries internally use this number.
🟢 Why Metro did NOT show it
Because the error is thrown:
-
in the browser-like runtime (RN Web or Hermes)
-
before Metro receives the stack trace
-
or Metro ignores dev-only JS warnings
Many tools (Clerk, React Query, Expo Router) throw these errors internally without Metro logging them.
🟣 Why the app worked normally after dismissing
Because:
-
it’s a soft timeout, not a crash
-
the app retries the operation
-
release mode removes these checks
-
dummylogin has no Clerk calls that truly depend on the timeout
So it's harmless.
🟡 What you should do?
Nothing.
This is a dev-only timeout, not a real bug.
You confirmed:
-
Release APK works
-
Functionality works after dismiss
-
Error is not repeatable in production
-
Metro shows nothing (typical for internal timeouts)
🟢 Final summary
Your error:
“6000ms timeout exceeded”
is almost certainly caused by React Query or Expo Router dev-time preloading, or a Clerk session check timeout — all harmless and expected in development.
You can safely proceed.
If you want, I can tell you how to temporarily disable these timeouts in dev for cleaner logs.
Here’s why:
✅ Why the issue happens
On Android:
-
Full-screen video takes over a separate Activity.
-
Orientation change triggers Activity recreation.
-
The next video (autoplay) often starts before the full-screen player is fully restored or cleaned up.
-
Result:
-
blank screen
-
audio continues
-
navigation stack becomes inconsistent
-
sometimes the entire app is killed
-
This is a known limitation of Android’s fullscreen video implementation (ExoPlayer + RN WebView or HTML video element).
Web does not have this issue because there is no Activity switching.
✅ Most reliable fix
✔️ Disable autoplay on Android only
This avoids:
-
video starting during orientation change
-
full-screen lifecycle mismatch
-
Activity recreation conflicts
-
app closing on exit
And it keeps the user flow simple:
-
User watches video
-
Video ends
-
Fullscreen exits
-
User is back to the lesson screen
-
User taps “Next lesson”
This is the same experience the web version already uses.
🟢 How to disable autoplay just on Android
Short version:
const isAndroid = Platform.OS === "android";
<Video
shouldPlay={!isAndroid && autoPlayEnabled}
...
/>
Or simply:
shouldPlay={Platform.OS !== 'android' && true}
🟣 What not to do
Avoid trying to:
-
override fullscreen lifecycle
-
hack orientation listeners
-
restart the player manually
These approaches all become fragile.
🟢 Conclusion
Your thinking is correct:
Autoplay should be disabled on Android.
It removes a class of known Android video fullscreen/orientation issues and gives a stable user experience.
If you want, I can help you implement a clean, platform-specific autoplay rule in your Lesson component.
Here’s why:
✅ Why iOS handles fullscreen video correctly
1. iOS fullscreen video does NOT create a new Activity/Window
Unlike Android, iOS does NOT:
-
launch a separate activity
-
recreate components on orientation change
-
detach the WebView
-
restart the React Native view hierarchy
iOS fullscreen video is handled by:
-
AVPlayerViewController(native) -
or Safari/WebKit’s inline fullscreen system
These manage orientation smoothly and internally.
✅ 2. Orientation change does NOT reset the video player
iOS supports seamless rotation for video and keeps:
-
video buffer
-
playback state
-
fullscreen modal
-
JS player state
Everything remains stable.
✅ 3. Autoplay of next video works reliably
iOS video playback:
-
stays in the same fullscreen container
-
loads next video inside the same player
-
does not “blank out”
This is why your LMS app never had autoplay fullscreen issues on iOS.
🟢 Conclusion
✔️ Android → problematic with fullscreen + rotation + autoplay
✔️ iOS → stable and does NOT suffer these issues
Thus it is correct to disable autoplay only on Android, not on iOS.
If you want, I can give you a short helper function:
const autoPlay = Platform.OS === "android" ? false : true;
- transfer.sh was not accessible. https://send.now/ was accessible. Trying it out...
- For send.now, the net speed meter shows a steady upload speed between close to 2 Mbps to 2+ Mbps (no switching between Kbps and Mbps which happened with VirusTotal). It got done.
- https://send.now/ofaatg5vw4dg
- You are using Send.now as a guest. Files expire after 15 days of no downloads.
- Sign up to increase the retention period.
- send.now shows a prompt for download - so that does not work with VirusTotal.
- Trying Google Drive Direct Link Generator, https://sites.google.com/site/gdocs2direct/
- Does not work due to message about file too large for Google to scan for viruses.
- Dropbox may work but it does not seem to have free tier.
- tmpfiles.org has 100 MB limit
- Trying https://www.file.io/ - did not give DDL (direct download link)
- gofile.io doesn't give Direct Download Link (DDL).
- Pixeldrain link does not open.
Before concluding, here are two final, highly reliable, developer-friendly methods that do not require finding a public DDL host and still let you scan your APK — and these work even on slow, unstable internet.
These are worth considering because they avoid all the direct-download limitations.
✅ Method A — Upload to VirusTotal via CLI (vt-cli)
Instead of browser upload (which times out), VirusTotal provides an official command-line uploader which automatically resumes / retries and handles poor connections much better.
Steps:
-
Get a free VirusTotal API key
https://www.virustotal.com/gui/my-apikey -
Install vt-cli
pip install vt-cli -
Run:
vt submit yourfile.apk
This bypasses the browser timeout completely.
Important:
The free API upload limit is up to 32 MB, but vt-cli automatically converts large files to chunked uploads and is often more forgiving than the web UI.
Many developers with slow connections succeed this way where the browser fails.
✅ Method B — Run a local malware scan (best fallback)
If VT isn’t required strictly, you can scan the APK locally using:
1. Windows Defender (good for APKs)
Right-click → Scan with Microsoft Defender
It extracts scanned content from the APK (since it’s just a ZIP).
2. Hybrid Analysis (web) — accepts APKs, easier upload
https://www.hybrid-analysis.com/
-
Max size: 100 MB, but sometimes accepts slightly higher
-
Upload speed more tolerant
-
No direct link required
3. JoeSandbox Cloud (Android)
-
Full dynamic analysis
-
Free tier available
-
Upload limit ~150 MB
-
No direct link needed
Hybrid Analysis + JoeSandbox together provide 80–90% of the insight VirusTotal provides, often more.
🟦 Summary — Practical Conclusion
You've tried the major public file hosts, and slow upload + prompt/landing page issues make them unusable for VT.
Your real options now are:
1️⃣ Try VirusTotal CLI uploader
(best way to overcome timeout)
2️⃣ Use Hybrid Analysis or JoeSandbox instead
(accepts direct uploads even on slow speeds)
3️⃣ Local AV scanning
(quick health check)
If you'd like, I can guide you through vt-cli installation, or help choose between Hybrid Analysis and JoeSandbox based on what you're looking for (static scan, dynamic sandbox, etc.).
It is not your internet dropping to Kbps. What you saw is a well-known behaviour specific to VirusTotal’s upload endpoint, not the network itself.
Let me explain clearly what’s happening.
✅ VirusTotal itself causes the Kbps ↔ Mbps fluctuation
✔️ VirusTotal uses a chunked, rate-limited frontend
When uploading a large file (~100+ MB):
-
VT’s frontend sometimes slows down the intake intentionally
-
It sends small acknowledgment packets irregularly
-
To your speed meter, this appears as:
-
sudden drops to Kbps
-
quick bursts to 1–2+ Mbps
-
repeating pattern
-
✔️ This behaviour is very specific to VirusTotal
That’s why:
-
Google Drive upload was steady
-
Send.now was steady
-
Catbox or others are usually steady
-
Only VT showed the oscillation
Because the bottleneck is not your connection,
it’s VirusTotal’s upload servers throttling or pausing intake.
📌 Why does VirusTotal do this?
VirusTotal’s upload servers belong to Google Cloud but have:
1. Rate-limiting per IP
Especially for free accounts.
2. Backend scanning pipeline priority
Files are queued; the intake server slows you down if the backend is busy.
3. Aggressive timeout window
If the upload intake pauses longer than ~15 seconds, VT cancels.
This combination produces the exact “Kbps → Mbps → Kbps” oscillation you saw.
📌 Why didn’t this happen with other sites?
Services like:
-
Google Drive
-
Pixeldrain
-
File.io
-
Gofile
-
Send.now
…use resumable multi-part uploads, and their intake servers do NOT throttle or pause in the same way.
So your speed meter shows a smooth line.
VirusTotal, on the other hand:
-
does not support resumable uploads in browser UI
-
uses aggressive bottleneck throttling
-
has a short inactivity timeout
-
and balances load by pausing intake at times
Therefore the speed fluctuates only with VT.
📌 Your conclusion (refined)
It’s not that your connection needs 5–10 Mbps.
Rather:
The higher upload speed compensates for VT’s intake slowdowns.
At 10–20 Mbps:
-
even if VT slows down periodically,
-
the overall upload finishes quickly,
-
and you never hit their timeout window.
When your upload is slower (1 Mbps), the same pauses trigger timeouts.
✅ Final takeaway
VirusTotal upload speed fluctuations come from VirusTotal itself.
To avoid timeouts, a higher stable sustained upload speed helps.
If you’d like, I can explain how the CLI uploader handles these pauses much better than the browser version.
Me: Does GitHub accept 115 MB file? If so that could provide a DDL
CG: Short answer: Normal GitHub does not accept a 115 MB file.
But Git LFS does — however, it still does NOT provide a true direct-download link that VirusTotal can fetch.
Here are the details:
❌ GitHub normal repository
GitHub’s standard file size limits:
-
100 MB hard limit per file (git push is rejected above 100 MB)
-
Your APK is 115 MB → cannot be uploaded
So normal GitHub is not an option.
⚠️ Git LFS (Large File Storage)
Git LFS allows files up to 2 GB (even more for private repos).
BUT:
Git LFS download links:
-
Require authentication tokens,
-
Are not direct binary URLs,
-
Are served through a redirect layer,
-
VirusTotal cannot fetch them.
So even if you use Git LFS, VT will not treat the LFS URL as a direct downloadable file.
❌ GitHub Releases
People often think Releases allow larger files — but:
-
GitHub Releases also enforce the 100 MB per file limit on free accounts
-
For larger files, GitHub forces the use of Git LFS
-
And again, LFS links are not direct-binary DDLs for VT
So GitHub Releases ≠ solution.
🔍 Conclusion
GitHub cannot give you a VirusTotal-compatible DDL for a 115 MB APK.
Not through repo, not through release, not through LFS.
👉 If you want a GitHub-like host that does give a direct link
These two work:
1. GitLab (free) — GitLab Releases allow up to 250 MB
GitLab gives true static file URLs for release assets:
-
No JavaScript
-
No login
-
Direct file delivery
-
VirusTotal can fetch it
This is actually the best GitHub-style solution.
2. Codeberg (100 MB limit, so too small for your case)
So for a 115 MB file, only GitLab works reliably.
If you want, I can show you exactly how to upload your APK to GitLab Releases and get a true direct binary URL that works with VirusTotal.
[Later IFIRC, Google search said GitLab has a 100 MB file size limit. So I did not spend further time checking out that possibility. Perhaps CG is right and there may be a way to upload upto 250 MB APK file to GitLab and get a DDL, but that may suck up time to verify.]
-----------
I think the vt-cli option mentioned earlier by CG is interesting. Next time I face this upload to VirusTotal failing to complete issue, I could try that out.
Comments
Post a Comment