IOS Asset Download Fails - On OTA Update

Does anyone have a bare IOS application working with expo updates and bundled assets hosted on your own S3 bucket? We’re experiencing the below issue meaning we can’t update any assets with an OTA update.

:bug: Bug Report

Summary of Issue

A bare expo IOS application fails to download changed assets from our own S3 bucket due to requiring the file extension.

  • expo export creates all assets in the assets folder with no file extension. e.g. cec49ef2741941ccb25a382cfa463189.
  • ios app is requesting assets/cec49ef2741941ccb25a382cfa463189.png and receives access denied due to the correct url actually being assets/cec49ef2741941ccb25a382cfa463189.
2020-07-23 17:01:00.543811+0100 Test App[7736:11806467] error loading asset cec49ef2741941ccb25a382cfa463189.png: <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>XXXX</RequestId><HostId>XXXX</HostId></Error>


  • ios - bare
  • S3 bucket hosting content of an expo-export
  Expo CLI 3.20.5 environment info:
      OS: macOS 10.15.4
      Shell: 5.7.1 - /bin/zsh
      Node: 14.6.0 - ~/.nvm/versions/node/v14.6.0/bin/node
      Yarn: 1.22.4 - ~/.yarn/bin/yarn
      npm: 6.14.6 - ~/.nvm/versions/node/v14.6.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
      Android Studio: 3.6 AI-192.7142.36.36.6392135
      Xcode: 11.6/11E708 - /usr/bin/xcodebuild
      expo: 37.0.10 => 37.0.10 
      react: 16.9.0 => 16.9.0 
      react-dom: 16.9.0 => 16.9.0 
      react-native: 0.61.5 => 0.61.5 

Steps to Reproduce

  • Build a bare IOS application with a couple of images
  • Run app
  • Change one of the images
  • Run an expo export and upload build to S3
  • Reload the native app to fetch the latest update
  • Receive error loading asset

Expected Behavior vs Actual Behavior

  • Expect the native app to use no .png when requesting files from the hosted update.
  • Expect expo export to generate assets with file extensions.

Looks like a bug in expo updates. Following fix should fixes the problem. Just need to use the URL defined in the assetUrlOverride if it is a valid URL.

Original code is in expo/EXUpdatesLegacyUpdate.m at master · expo/expo · GitHub

+ (NSURL *)bundledAssetBaseUrlWithManifest:(NSDictionary *)manifest
  NSURL *manifestUrl = [EXUpdatesConfig sharedInstance].updateUrl;
  NSString *host =;
  if (!host ||
      [host containsString:kEXUpdatesExpoIoDomain] ||
      [host containsString:kEXUpdatesExpHostDomain] ||
      [host containsString:kEXUpdatesExpoTestDomain]) {
    return [NSURL URLWithString:kEXUpdatesExpoAssetBaseUrl];
  } else {
    NSString *assetsPath = manifest[@"assetUrlOverride"] ?: @"assets";
    if ([assetsPath hasPrefix:@"http://"] || [assetsPath hasPrefix:@"https://"]) {
          return [NSURL URLWithString:assetsPath];
      } else {
          return [manifestUrl.URLByDeletingLastPathComponent URLByAppendingPathComponent:assetsPath];