OTA updates - Failed to download new update

I am trying to add OTA updates to my expo application with EAS build as long as a custom server to avoid using EAS update paid features from expo but I am running into an issue. (I copy pasted the expo-updates-server folder from github expo/custom-expo-updates-server)

When using EAS update, everything works as expected but I am quickly reaching the 1000 free updates limit.

Here is the updates section in my app.json and how I configure runtimeVersion

vanity.domains | homepage only hosts the expo-updates-server from the github.


"updates": {
  "enabled": true,
  "checkAutomatically": "ON_LOAD",
  "url": "https://custom-domain.com/api/manifest",
  "codeSigningCertificate": "./code-signing/certificate.pem",
  "codeSigningMetadata": {
    "keyid": "main",
    "alg": "rsa-v1_5-sha256"
"runtimeVersion": {
  "policy": "sdkVersion"

In my App.tsx I also have this to listen to any update and try to download it.

useEffect(() => {
}, []);

async function checkForUpdates() {
  try {
    const update = await Updates.checkForUpdateAsync();
    if (update.isAvailable) {
      await Updates.fetchUpdateAsync();       ---> causes the error
      await Updates.reloadAsync();
  } catch (err) {

I also have Sentry setup to keep track of any error on the app and everytime I run a new update and the app tries to fetch it by calling my update url and it tells me the error is coming from await Updates.fetchUpdateAsync();

I also have a eas.json file for the configuration:

  "cli": {
    "version": ">= 3.1.1"
  "build": {
    "development": {
      "channel": "development",
      "developmentClient": true,
      "distribution": "internal"
    "staging": {
      "distribution": "internal",
      "channel": "staging",
      "env": {
        "API_URL": "api",

Here is the flow from building to updating:

  1. Build the app: Run eas build -p ios --profile staging. This goes to the expo.dev dashboard. Everything works here, I am able to download the app on my device from the QR code after the build is finished.
  2. Make some changes on my app (change a title or something like this)
  3. Create the update from the server: Run npm run expo-publish in expo-updates-server folder from expo/custom-expo-updates-server. This goes to my client folder, run expo export --experimental-bundle and copies the dist folder to /updates folder in the server.
  4. After force-quitting the app and re-launching it, a request is maid to my custom server, the checkForUpdateAsync() passes but fetchUpdateAsync() fails and I get "Failed to download new update" on Sentry.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.