Retool Mobile — Image upload works on web but fails in mobile simulator (GCS upload)

Hi Retool team,

I'm experiencing inconsistent behavior when uploading images using the Retool mobile app vs web browser.

Environment

  • Retool Cloud

  • Retool Mobile App Simulator

  • Google Cloud Storage (GCS) upload

  • ImageInput / Camera capture component

  • Custom JS upload handler (base64 conversion + upload)

Issue

Uploading images works correctly when using the web browser, but fails when using the Retool mobile app simulator.

Behavior

Web browser

  • Select image → upload works

  • File successfully uploads to GCS

  • No errors

Retool Mobile Simulator

  • Capture or upload image

  • Upload fails with error

  • Same handler and query used

Implementation Details

  • Mobile files return uri which I convert to base64 using:
utils.getDataByObjectURL(file.uri)
  • Upload triggered via Retool query to GCS

  • Bucket permissions tested (private / authenticated/ public)

Question

Is this expected behavior or a known limitation with:

  • Retool Mobile file handling?

  • Mobile authentication context?

  • Camera/ImageInput output format?

  • Mobile simulator environment?

Is there a recommended best practice for handling mobile image uploads to GCS in Retool?

Expected Behavior

Mobile upload should behave the same as web upload.

Reproduction Steps

  1. Create ImageInput component

  2. Capture image from mobile simulator

  3. Convert file to base64 using file.uri

  4. Upload to GCS

  5. Upload fails

Any guidance would be appreciated. Thank you!

Update / Resolution + Lesson Learned

Root cause identified for mobile image upload failing in Retool Mobile while working in web.

:cross_mark: Root Cause

Mobile camera returns the file type as:

application/octet-stream

Our previous logic used:

let extension = type.split("/")[1];

This saved the file with an invalid extension (octet-stream), which caused upload and preview failures.

:white_check_mark: Fix

Normalize the file type by forcing a valid image extension:

let extension = type == "application/octet-stream" ? "jpg" : type.split("/")[1];

This ensures the uploaded file is treated as a valid image format and resolves the mobile upload issue.


:pushpin: Additional Lesson Learned

The error shown during debugging was:

SignatureDoesNotMatch — Access denied

This suggested a signing/authentication issue, but the real problem was the incorrect file type affecting the upload request.

Feedback for Retool: Improving mobile upload error messaging would help — the current error was far from the actual root cause and made troubleshooting more difficult.