Repository navigation
Map ATT errors to UniversalBleErrorCode on Apple - #350
Merged
Merged
Conversation
A GATT operation the peripheral refuses fails with an NSError in CBATTErrorDomain. toFlutterError() looked its numeric code up in mapErrorCodeToEnum, which matches names only, so every refusal reached Dart as unknownError. ATT codes now map as Android's gattStatusToUniversalBleErrorCode maps them; other domains are unchanged. The example's RunnerTests held a template test that no longer compiled (UniversalBlePlugin has no handle method since the move to Pigeon); it now tests this mapping.
alvynfash
force-pushed
the
apple-att-error-codes
branch
from
October 16, 2026 09:17
2d1d8d5 to
d00a1db
Compare
fotiDim
approved these changes
Oct 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #348.
What
On iOS and macOS, a read, write or subscription that the peripheral refuses now reports the matching
UniversalBleErrorCode(insufficientEncryption,insufficientAuthentication,readNotPermitted, …), as Android already does. Until now every such refusal reached Dart asunknownError.Why it happened
The refusal arrives as an
NSErrorinCBATTErrorDomain.Error.toFlutterError()passed its numeric code tomapErrorCodeToEnum, which matches names only ("failed","devicenotfound", …). A number never matches, so the result was always.unknownError.The change
attErrorToUniversalBleErrorCodemaps everyCBATTError.Codeto the same value Android'sgattStatusToUniversalBleErrorCodegives the same ATT code. A refusal therefore reads the same on both platforms.toFlutterError()uses that mapping only for errors inCBATTErrorDomain. Every other domain goes throughmapErrorCodeToEnumas before, becauseCBErrorDomainreuses the same small numbers for other meanings (its 15 is encryption timed out, ATT's 15 is insufficient encryption).messageanddetailsare unchanged:detailsstill carries the numeric code.Tests
example/ios/RunnerTestsheld the Flutter template test, which no longer compiles (UniversalBlePluginhas had nohandlemethod since the move to Pigeon). It now tests this mapping:insufficientEncryptionrefusal);CBErrorDomainerror with the same number is not read as an ATT code.To run them:
xcodebuild test -workspace example/ios/Runner.xcworkspace -scheme Runner -destination '<simulator>'. They pass on an iPhone 17 simulator (iOS 27). With the oldtoFlutterError()the first test fails.With Xcode 27 the example needs
IPHONEOS_DEPLOYMENT_TARGET=15.0on the command line, because its 13.1 is below that SDK's minimum. This PR does not change the deployment target.flutter analyzeandflutter testpass (285 tests).Seen on hardware
A Leica DISTO D2-2 refuses an unpaired read with "Encryption is insufficient" (ATT 15). That read is what makes iOS pair the device, and the app has to tell this refusal apart from any other failure.