ITMS-90683: “Missing purpose string” oplossen met Expo
Door Mehdi Azizi
Gepubliceerd op , 6 min
ITMS-90683 Missing purpose string: waarom Apple je build weigert, welke sleutel je in app.json zet met Expo en hoe je ontbrekende sleutels vooraf vindt.
ITMS-90683 is een automatische afwijzing van Apple. Je krijgt hem per e-mail kort nadat je je build hebt verstuurd, nog vóór er een mens naar kijkt. Hij betekent dat er in je Info.plist een zin ontbreekt die uitlegt waarom de app een gevoelig gegeven gebruikt. Oplossen doe je in twee stappen: zet de sleutel uit het bericht in ios.infoPlist en maak een nieuwe build.
Ik kreeg hem zelf op Solys, mijn wekker met minigames, voor een gegeven dat de app niet eens gebruikt. Hier lees je wat het bericht betekent, waarom je hem krijgt en hoe je hem voorkomt.
Wat betekent de fout ITMS-90683?
Het volledige bericht heet "ITMS-90683: Missing purpose string in Info.plist". Het zegt dat de code van je app verwijst naar een API die gevoelige gegevens aanraakt (foto's, camera, microfoon, locatie, contacten), en dat je Info.plist de bijbehorende beschrijvingssleutel mist. Het bericht noemt die sleutel, bijvoorbeeld NSPhotoLibraryUsageDescription.
Die beschrijvende zin heet een "purpose string". Het is de tekst die iOS laat zien in het venster waarin om toestemming wordt gevraagd. Apple schrijft het in zijn documentatie over toegang tot beschermde bronnen: App Review weigert apps waarvan de code deze bronnen gebruikt zonder purpose string.
Het is geen afwijzing door een reviewer. De controle is automatisch en gebeurt bij de levering van de build, vóór de review, net als ITMS-91053 voor het privacymanifest. De build wordt geweigerd en je moet een nieuwe sturen.
Waarom Apple weigert terwijl je app dat gegeven niet gebruikt
Dit is het verrassende deel. Apple analyseert de code in je build, niet wat je app echt doet. Bevat een library die je meelevert een verwijzing naar de fotobibliotheek, dan is de sleutel verplicht, ook als geen enkel scherm ooit om toegang tot foto's vraagt. Apple zegt het zelf in het bericht: een externe library of SDK kan naar deze API's verwijzen, en de purpose string blijft verplicht.
Mijn geval, op 26 september 2026. Bij het opschonen van de configuratie van Solys had ik de sleutel NSPhotoLibraryUsageDescription weggehaald, want de app doet niets met foto's. De volgende build werd geweigerd met ITMS-90683. De oorzaak: twee Expo-libraries die de app gebruikt, expo-image en expo-file-system, bevatten code die naar de fotobibliotheek verwijst. De vorige build kwam er wel door, omdat de sleutel er toen nog in stond.
De les: je haalt een beschrijvingssleutel niet weg "omdat je hem niet gebruikt". Dat doe je pas als geen enkele library in de build nog naar de API verwijst.
De meest voorkomende sleutels
NSPhotoLibraryUsageDescription: foto's lezen of schrijven.NSPhotoLibraryAddUsageDescription: foto's toevoegen, zonder lezen.NSCameraUsageDescription: camera.NSMicrophoneUsageDescription: microfoon.NSLocationWhenInUseUsageDescription: locatie tijdens gebruik.NSContactsUsageDescription: contacten.NSUserTrackingUsageDescription: advertentietracking (App Tracking Transparency).
Apple beschrijft elke sleutel in zijn documentatie, bijvoorbeeld die van NSPhotoLibraryUsageDescription: die is verplicht zodra de app een API gebruikt die in de fotobibliotheek leest of schrijft.
ITMS-90683 oplossen in een Expo-app
- Noteer de sleutel uit de e-mail van Apple. Het bericht geeft de exacte naam.
- Zet hem in je configuratie, onder
ios.infoPlist, zoals de Expo-documentatie over permissies aangeeft:
{
"expo": {
"ios": {
"infoPlist": {
"NSPhotoLibraryUsageDescription": "Solys gebruikt je foto's niet. Deze toestemming wordt nooit gevraagd."
}
}
}
}
- Maak een nieuwe build. Expo zegt het erbij: een wijziging in de Info.plist gaat niet via een update op afstand, je hebt een nieuw binary nodig.
- Stuur de build opnieuw naar Apple en selecteer hem in je versie.
Een valkuil als je app vertaald is: taalbestanden vertalen een sleutel, ze declareren hem niet. De sleutel moet eerst bestaan in ios.infoPlist (of in de configuratie van de betreffende plugin). Anders kan de app crashen bij de eerste aanroep.
Welke zin schrijf je als je app het gegeven niet gebruikt?
Apple vraagt om een juiste, nuttige en precieze beschrijving. Gebruikt je app het gegeven echt, zeg dan in één zin waarvoor: "De app gebruikt de camera om de barcode van je ticket te scannen."
Staat de sleutel er alleen vanwege een library, dan geeft Apple twee oplossingen: de zin schrijven, of de code verwijderen die het gegeven gebruikt. Komt die code uit een library, dan kun je hem niet zomaar weghalen. Op Solys schreef ik dus gewoon de waarheid: "Solys gebruikt je foto's niet. Deze toestemming wordt nooit gevraagd." Dat is een pragmatische keuze: de volgende build kwam door de levering, maar ik kan je niet beloven dat Apple deze zin altijd accepteert.
Ontbrekende sleutels vinden vóór het versturen
Vanuit de root van je project toont dit commando de bestanden van libraries waarvan de iOS-code verwijst naar de meest gecontroleerde API's:
grep -rlE "PHPhotoLibrary|AVCaptureDevice|CLLocationManager|CNContactStore|EKEventStore|ATTrackingManager" \
node_modules/*/ios node_modules/@*/*/ios
Elke naam hoort bij een gegeven: PHPhotoLibrary voor foto's, AVCaptureDevice voor camera en microfoon, CLLocationManager voor locatie, CNContactStore voor contacten, EKEventStore voor de agenda, ATTrackingManager voor tracking. Controleer bij elk resultaat of de bijbehorende beschrijvingssleutel in je configuratie staat.
Dit vangnet vangt de gevallen die ik ben tegengekomen. Het vervangt het lezen van de e-mail van Apple niet: die blijft de enige betrouwbare lijst, net als bij de niet-publieke API's van ITMS-90338. Sinds die afwijzing doe ik deze check vóór elke build: hij kost een paar seconden, terwijl een ITMS-90683 je een build kost plus de tijd om hem opnieuw te maken.
Je build versturen zonder nare verrassingen
ITMS-90683 los je snel op als je hem kunt lezen, net als ITMS-90725, die over de Xcode-versie gaat. De afwijzingen daarna, die van een reviewer, vragen meer afstand: de aanpak staat op de pagina app afgewezen door Apple, en de meest voorkomende redenen vind je in waarom Apple een app weigert.
Wil je je dossier vóór het versturen checken? De Apple Review Kit bundelt mijn checklist en Claude Code-skills die je project nalopen. Loopt je inzending vast en wil je een menselijke blik, boek een uur met mij: we lopen je project samen door via video, op jouw scherm. En bereid je je eerste release voor, doe dan je gratis diagnose: die zet de stappen op volgorde en stuurt je mijn checklist tegen Apple-afwijzingen.
Veelgestelde vragen
Is ITMS-90683 een afwijzing door App Review?
Niet in de zin van een menselijke reviewer. Het is een automatische controle op de build bij de levering, vóór de review, net als ITMS-90717 voor het icoon. Niemand heeft je app geopend. De build wordt geweigerd: je moet de Info.plist corrigeren en een nieuwe sturen.
Waarom vraagt Apple een sleutel voor een gegeven dat mijn app niet gebruikt?
Omdat Apple de code in de build analyseert, niet het gedrag van de app. Verwijst een meegeleverde library naar de fotobibliotheek of de camera, dan is de beschrijvingssleutel verplicht, ook als geen enkel scherm ooit om die toegang vraagt.
Kun je ITMS-90683 oplossen met een update op afstand?
Nee. De ontbrekende sleutel zit in de Info.plist, en die hoort bij het binary. Een update op afstand past dat bestand niet aan: je moet een nieuwe build maken en die opnieuw naar Apple sturen.
Waar zet je NSPhotoLibraryUsageDescription in een Expo-project?
In je appconfiguratie, onder ios.infoPlist, met een zin die het gebruik beschrijft. Sommige libraries bieden ook een eigen instelling in hun plugin, die andere sleutels kan toevoegen, zoals een achtergrondmodus. In beide gevallen moet de sleutel in de basisconfiguratie staan, niet alleen in de vertaalbestanden.
Moet je ongebruikte beschrijvingssleutels weghalen?
Alleen als geen enkele library in de build nog naar de betreffende API verwijst. Anders wordt je volgende inzending geweigerd met ITMS-90683. Zoek voordat je een sleutel weghaalt de naam van de API op in de iOS-code van je dependencies.