Reader pairs, then permanently “Unable to establish a secure connection to Square” — retryConnection() returns UNABLE_TO_RETRY even on a freshly re-paired reader
Running mobile-payments-sdk-react-native 2026.8.1 (native iOS SDK 2.6.0) on Expo 56.0.18 / React Native 0.85.3. A Square Reader pairs over Bluetooth fine, but never reaches Ready. getReaders() shows exactly one reader stuck at:
I found a couple of older threads here describing this exact error, and one was resolved via the App Attest entitlement (missing com.apple.developer.devicecheck.appattest-environment causing sandbox attestation on internally-distributed builds). I did that fix exactly — added the entitlement with value production, enabled App Attest on the App ID, rebuilt with a fresh provisioning profile — and confirmed directly via codesign -d --entitlements :- on the shipped binary that it’s actually there with the right value, and that the provisioning profile allows it. Didn’t fix it for us.
Before posting I went pretty deep trying to rule things out on my own side first:
Confirmed the app is genuinely running native SDK 2.6.0 (checked the framework’s own Info.plist, not just what I thought I’d pinned).
Reproduces identically on two completely different networks (office Wi-Fi and a cellular hotspot), and I confirmed via the SDK binary’s own strings that SECURE_CONNECTION_TO_SQUARE_FAILURE and SECURE_CONNECTION_NETWORK_FAILURE are separate reasons — we’re consistently getting the former.
Device clock is set automatically.
Device authorization succeeds fine, no authorization error anywhere.
Our iOS signature registration (Bundle ID + Team ID) on the console already matches the shipped binary’s signing identity exactly.
Did a full hardware reset on the reader itself (held reset until it flashed), then re-paired — no change.
This is the one I think is most useful: ReaderManager.retryConnection(_:) and ReaderManager.forget(_:) are real public methods on the underlying SDK (visible in the generated -Swift.h header) that this RN plugin doesn’t expose to JS — only forget() does, retryConnection()/rebootReader() don’t. I patched both in locally just to get more signal. Calling retryConnection() on the stuck reader consistently returns UNABLE_TO_RETRY — not “already connecting,” an actual refusal. Calling forget() genuinely clears it (getReaders() drops to 0). But re-pairing after that gets a brand new reader ID and hits the exact same failure immediately, on the very first attempt.
That last part is why I’m posting instead of continuing to poke at it myself — a brand-new pairing session failing identically on first contact doesn’t look like anything cached or stale on our end anymore, and I’ve run out of client-side state to reset.
Would really appreciate it if someone could check the server-side rejection reason for our reader’s secure-session attempts (happy to send Application ID / reader serial / timestamps privately rather than posting them here) — and specifically, is this rejection happening during app-attestation, or somewhere else in the handshake?
To look up your reader’s secure-session attempts on our side, we’ll need:
Application ID (sq0idp-...)
Reader serial number (printed on the device)
UTC timestamps of two or three recent failed attempts — approximate is fine
One question: does this reproduce on a device running a stable (non-beta) iOS release? As you noted, the secure-session setup involves Apple’s app attestation, and we’d like to rule beta-OS attestation behavior in or out before digging into account-level causes.
On your three questions: (1) the server-side rejection reason and (3) anything account-level — we can check both once we have the identifiers above; (2) which step is rejecting — the same server-side records should tell us that too.
On the secondary ask (retryConnection() / rebootReader() in the RN bridge): noted — we’ll follow up on that separately.
Reproduces on a stable, non-beta iOS release. Tested on an iPad mini running iOS 26.6.1 (not beta) — same failure, same SECURE_CONNECTION_TO_SQUARE_FAILURE. Retested again today (9/10) on the same device, same result. So this isn’t iOS 27 beta attestation behavior; it’s happening on production-grade iOS too.
One clarification on our own config, in case it’s useful context: this build points at a Square Application ID we use for our lower/dev environments — it’s still a real production Square application, not a sandbox one.
Identifiers you asked for:
Application ID: sq0idp-brKtOkm8umJA3SZRnelLmA (our lower-environment production App ID, used for this testing)
Reader serial number: SN230LS14606605784
Failure timestamps (UTC), from device console logs during active testing:
2026-09-09 15:56:10 UTC
2026-09-09 16:36:39 UTC
2026-09-09 17:09:54 UTC
2026-09-10: additional testing on the iOS 26.6.1 device, same failure (exact UTC timestamp available on request if useful — today’s log excerpt didn’t have a timestamped event to pull from directly)
For September 9th and 10th, this was the only activity on this device and against this Application ID — no other testing or production traffic in that window, so any server-side records you find for that device/App ID in that range should all be from us.
Resolved, the reader now reaches Ready. The root cause was two Square SDKs’ build phases both embedding CorePaymentCard.framework to the same path, with the In-App Payments copy (4.18.1) overwriting the Mobile Payments SDK one. The fix was reordering the build phases so the Mobile Payments SDK setup runs last, and after a fresh pairing the secure session now succeeds. Thanks for the help narrowing it to the framework check.