Keychain writes silently failed (missing keychain-access-groups entitlement on simulator), causing the token to disappear between handleTokenResponse and the first API call. The in-memory cache ensures the token is always available within the session; the keychain still persists it across launches when entitlements allow.