When owner is set in app.json OTA updates do not work

We have two projects, a staging project and a production project.

We hit a strange issue where having the owner prop set in the app.json means that for our production project OTA updates don’t work whereas on our staging project they do.

If I remove the owner prop then OTA updates work on both projects.

We’ve had the owner prop set as the same value for the past 3 months, and sometime in the past 2 weeks OTA updates have stopped working on production.

Is this an Expo bug? From what I can tell the owner prop is something to do with EAS builds, however we don’t have an EAS plan.

Hey @alastairtaft, what type of project is it? (Managed or Bare?) Also, can you try to reproduce this behavior with a new project?


It’s a managed project, sorry I really don’t know how to repo it, seems a really weird
scenario, if you’re able to look at the organisation linked to my account (petspot). It’s the two projects under there.

The OTA update is done from the Expo petspotdeveloper account and it doesn’t work when the owner attribute is set on the production project. That said when building a binary locally with the same Expo account it does do a successful over the air update, but doing an OTA update only locally does not work.

Fyi, the “owner” existed long before EAS. It’s to do with teams/organisations.


Yeah correct we had it set 3 months ago, but in the docs it states

The Expo account name of the team owner, only applicable if you are enrolled in the EAS Priority Plan

So according to that I would think it should only have an effect if I’m enrolled in the EAS Priority Plan, which I’m not.

After searching around I could not find any mention that that prop should have an impact on OTA updates

Additional update.

I’ve applied my production fix of removing the owner attribute but this seems to break my staging app where the owner attribute seems to be required.

That is not actually true :slight_smile: It definitely has an effect, even if you’re not using EAS.

Well, I’m not sure what’s going on in your case, but as far as I understand it, it works something like this:
Assume you have an organisation account called “org” and a team member account called “member”.
Now if you do not have the “owner” option set, when you run expo publish, it will publish to @member/slug. If you set the “owner” option to “org”, then publish, it will publish to @org/slug.
If your app was built with the owner unset, then it will try to fetch an OTA update from @member/slug. If it was built with the owner set to org, it will fetch the OTA update from @org/slug.

Thanks for the explanation @wodin, that makes sense and I think something like that must be going on. Do you know how to check which owner an app is published/built under?

I suppose, try:

expo publish:history --count 100

with the “owner” set and unset.

And check the builds available builds on https://expo.dev (or maybe run eas build:list --status=finished with “owner” set and unset.) You should also be able to find a reference to @user/slug in the app bundles of you download and unzip them.

Thanks, on http://expo.dev you can see the owner, I think, under additional details on the build. The prod one is published under a user and the staging one is published under the organisation, so this must be it. Thanks for your help, I guess I must remember and check to having "owner": "<organisation>" set whenever I create a binary.

Any reason not to set it once and for all?

Nope. owner wasn’t on my radar for affecting OTAs. I thought OTAs were linked to the Expo version and the slug. Now I know to always check it’s set to the org when doing anything.

OK. What I mean is, why not just set it in app.json and forget about it? Why do you need to check it every time? :slight_smile:

Or I suppose you could create a pre-commit hook and/or GitHub action or something to make sure.

I have done, it’s been set for the past 3 months. That said for one reason or another I ended up with a build under a different owner, so I must have changed it when creating the binary manually.