Skip to content

ClassCastException when instantiating Peripheral #885

@brendanw

Description

@brendanw
Hardware Model:     iPhone17,1
Role:               Foreground
OS Version:         iOS 18.3.2


kotlin.ClassCastException: class com.juul.kable.PeripheralDelegate.Response.DidDiscoverServices cannot be cast to class com.juul.kable.PeripheralDelegate.Response.DidDiscoverCharacteristicsForService

0  BaseBetaiOS +0x4c4ec            ThrowClassCastException (RuntimeUtils.kt:39:11)
1  BaseBetaiOS +0x11dd598          <inlined-out:execute> (Connection.kt:125:12)
2  BaseBetaiOS +0x2e5fc            kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#invokeSuspend(kotlin.Result<kotlin.Any?>){}kotlin.Any?-trampoline (ContinuationImpl.kt:50:5)
3  BaseBetaiOS +0x18ea90           kfun:kotlin.coroutines.Continuation#resumeWith(kotlin.Result<1:0>){}-trampoline (Continuation.kt:26:5)
4  BaseBetaiOS +0x1b13ac           kfun:kotlinx.coroutines.Runnable#run(){}-trampoline (Runnable.kt:12:5)
5  BaseBetaiOS +0x24e4040          ___6f72672e6a6574627261696e732e6b6f746c696e783a6b6f746c696e782d636f726f7574696e65732d636f72652f6f70742f6275696c644167656e742f776f726b2f343465633665383530643563363366302f6b6f746c696e782d636f726f7574696e65732d636f72652f6e617469766544617277696e2f7372632f44697370617463686572732e6b74_knbridge2_block_invoke
6  libdispatch.dylib +0x2244       __dispatch_call_block_and_release
7  libdispatch.dylib +0x3fa4       __dispatch_client_callout
8  libdispatch.dylib +0x70f0       __dispatch_queue_override_invoke
9  libdispatch.dylib +0x15ebc      __dispatch_root_queue_drain
10 libdispatch.dylib +0x166c0      __dispatch_worker_thread2
11 libsystem_pthread.dylib +0x3640 __pthread_wqthread
12 libsystem_pthread.dylib +0x1470 _start_wqthread

Notes from Deepseek about the crash

If the connection is interrupted/reset during service discovery:

1. CoreBluetooth might automatically rediscover services
2. Delegate methods can be called out of sequence
3. Pending responses might be flushed to the queue in unexpected order

Reproduction Scenario

1. Sequence starts normally:

discoverServices() → DidDiscoverServices

discoverCharacteristics() → Expect DidDiscoverCharacteristicsForService

2. During transient connection failure:

CoreBluetooth automatically retries service discovery

didDiscoverServices delegate method is called again

This response gets queued before characteristic discovery completes

3. Code flow:

execute<DidDiscoverCharacteristicsForService> expects characteristic response

Actually receives service discovery response from retry

as? T cast fails

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions