I'm new to Kotlin Multiplatform, and I'm trying to make my own app. For now, my project work in Android simulator: I'm correctly connecting to my database and all. But in my iOS simulator, I'm not even able to connect to it, even though I already checked my internet connection and it works just fine. It fails systematically at the initialization I think, because I'm not even trying to get my values userMail/userPassword to sign in supabase for authentification via POST request... Here are the logs.
In xCode:
nw_connection_copy_connected_local_endpoint_block_invoke [C9] Connection has no local endpoint
nw_connection_copy_connected_local_endpoint_block_invoke [C9] Connection has no local endpoint
quic_conn_retire_dcid unable to find DCID 015f1e916872b5bc355d0a91e3728c9c04bcaa63
quic_conn_change_current_path [C9.1.1.1:2] [-015f1e916872b5bc355d0a91e3728c9c04bcaa63] tried to change paths, but no alternatives were found
nw_flow_service_writes Failing write request <nw_write_request> [57: Socket is not connected]
nw_write_request_report [C9] Send failed with error "Socket is not connected"
Task <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5> HTTP load failed, 341/0 bytes (error code: -1005 [4:-4])
Connection 9: write error 1:57
Task <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5> finished with error [-1005] Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x600000c471b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x60000213b250 [0x1e6ebb4f0]>{length = 16, capacity = 16, bytes = 0x100201bbac4095f60000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, NSErrorFailingURLKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, _kCFStreamErrorDomainKey=4}
nw_protocol_implementation_lookup_path [C9.1.1.1:2] No path found for 3d4ff1e623efddc2
nw_endpoint_handler_unregister_context [C9.1.1.1 172.64.149.246:443 failed socket-flow (satisfied (Path is satisfied), interface: en1[802.11], uses wifi)] Cannot unregister after flow table is released
Connection 9: received failure notification
nw_endpoint_flow_fillout_data_transfer_snapshot copy_info() returned NULL
nw_connection_copy_connected_local_endpoint_block_invoke [C9] Connection has no local endpoint
š“ (Supabase-Core) POST request to endpoint /auth/v1/token failed with exception Exception in http request: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x600000c471b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x60000213b250 [0x1e6ebb4f0]>{length = 16, capacity = 16, bytes = 0x100201bbac4095f60000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, NSErrorFailingURLKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, _kCFStreamErrorDomainKey=4}
io.ktor.client.engine.darwin.DarwinHttpRequestException: Exception in http request: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x600000c471b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x60000213b250 [0x1e6ebb4f0]>{length = 16, capacity = 16, bytes = 0x100201bbac4095f60000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, NSErrorFailingURLKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, _kCFStreamErrorDomainKey=4}
at 0 Job.debug.dylib 0x1083f1303 kfun:kotlin.Throwable#<init>(kotlin.String?){} + 99
at 1 Job.debug.dylib 0x1083eb18f kfun:kotlin.Exception#<init>(kotlin.String?){} + 95
at 2 Job.debug.dylib 0x108fe3bff kfun:kotlinx.io.IOException#<init>(kotlin.String?){} + 95
at 3 Job.debug.dylib 0x109189397 kfun:io.ktor.client.engine.darwin.DarwinHttpRequestException#<init>(platform.Foundation.NSError){} + 183
at 4 Job.debug.dylib 0x10918e2eb kfun:io.ktor.client.engine.darwin#handleNSError(io.ktor.client.request.HttpRequestData;platform.Foundation.NSError){}kotlin.Throwable + 359
at 5 Job.debug.dylib 0x109192cb3 kfun:io.ktor.client.engine.darwin.internal.DarwinTaskHandler#complete(platform.Foundation.NSURLSessionTask;platform.Foundation.NSError?){} + 407
at 6 Job.debug.dylib 0x10918b72f kfun:io.ktor.client.engine.darwin.KtorNSURLSessionDelegate#objc:URLSession:task:didCompleteWithError: + 535
at 7 Job.debug.dylib 0x10918c933 _696f2e6b746f723a6b746f722d636c69656e742d64617277696e2f6f70742f6275696c644167656e742f776f726b2f386435343762393734613762653231662f6b746f722d636c69656e742f6b746f722d636c69656e742d64617277696e2f64617277696e2f7372632f696f2f6b746f722f636c69656e742f656e67696e652f64617277696e2f4b746f724e5355524c53657373696f6e44656c65676174652e6b74_knbridge8 + 275
at 8 CFNetwork 0x1848a6aaf __79-[__NSCFURLSessionDelegateWrapper task:didCompleteWithError:completionHandler:]_block_invoke + 31
at 9 Foundation 0x180e8f26f __NSINDEXSET_IS_CALLING_OUT_TO_A_BOOL_BLOCK__ + 15
at 10 Foundation 0x180eec7f7 -[NSBlockOperation main] + 91
at 11 Foundation 0x180eef44f __NSOPERATION_IS_INVOKING_MAIN__ + 11
at 12 Foundation 0x180eeba33 -[NSOperation start] + 611
at 13 Foundation 0x180eefb9b __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ + 11
at 14 Foundation 0x180eef8b3 __NSOQSchedule_f + 159
at 15 libdispatch.dylib 0x1037b3d23 _dispatch_block_async_invoke2 + 103
at 16 libdispatch.dylib 0x1037bd797 _dispatch_client_callout + 11
at 17 libdispatch.dylib 0x1037a75b3 _dispatch_continuation_pop + 739
at 18 libdispatch.dylib 0x1037dae93 _dispatch_async_redirect_invoke + 699
at 19 libdispatch.dylib 0x1037b728f _dispatch_root_queue_drain + 355
at 20 libdispatch.dylib 0x1037b7dd3 _dispatch_worker_thread2 + 255
at 21 libsystem_pthread.dylib 0x102dceb8f _pthread_wqthread + 227
at 22 libsystem_pthread.dylib 0x102dcd98b start_wqthread + 7
š“ (Supabase-Auth) Couldn't reach Supabase. Either the address doesn't exist or the network might not be on. Retrying in 10s...
io.github.jan.supabase.exceptions.HttpRequestException: HTTP request to https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token (POST) failed with message: Exception in http request: Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x600000c471b0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x60000213b250 [0x1e6ebb4f0]>{length = 16, capacity = 16, bytes = 0x100201bbac4095f60000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <501EE373-9B04-4CDA-B9D4-C15FF4D418B8>.<5>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, NSErrorFailingURLKey=https://urlxxxx.supabase.co/auth/v1/token?grant_type=refresh_token, _kCFStreamErrorDomainKey=4}
at 0 Job.debug.dylib 0x1083f1303 kfun:kotlin.Throwable#<init>(kotlin.String?){} + 99
at 1 Job.debug.dylib 0x1083eb18f kfun:kotlin.Exception#<init>(kotlin.String?){} + 95
at 2 Job.debug.dylib 0x108fe3bff kfun:kotlinx.io.IOException#<init>(kotlin.String?){} + 95
at 3 Job.debug.dylib 0x1090ebae3 kfun:io.github.jan.supabase.exceptions.HttpRequestException#<init>(kotlin.String;io.ktor.client.request.HttpRequestBuilder){} + 663
at 4 Job.debug.dylib 0x1090ef54f kfun:io.github.jan.supabase.network.KtorSupabaseHttpClient.$requestCOROUTINE$0.invokeSuspend#internal + 5031
at 5 Job.debug.dylib 0x1085292ef kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#invokeSuspend(kotlin.Result<kotlin.Any?>){}kotlin.Any?-trampoline + 67
at 6 Job.debug.dylib 0x1083f660f kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 691
at 7 Job.debug.dylib 0x1085293cf kfun:kotlin.coroutines.Continuation#resumeWith(kotlin.Result<1:0>){}-trampoline + 99
at 8 Job.debug.dylib 0x108610553 kfun:kotlinx.coroutines.DispatchedTask#run(){} + 1787
at 9 Job.debug.dylib 0x10864157f kfun:kotlinx.coroutines.Runnable#run(){}-trampoline + 91
at 10 Job.debug.dylib 0x10863c27b kfun:kotlinx.coroutines.DarwinGlobalQueueDispatcher.dispatch$lambda$0#internal + 119
at 11 Job.debug.dylib 0x10863c2d7 kfun:kotlinx.coroutines.DarwinGlobalQueueDispatcher.$dispatch$lambda$0$FUNCTION_REFERENCE$0.invoke#internal + 71
at 12 Job.debug.dylib 0x10863c3a7 kfun:kotlinx.coroutines.DarwinGlobalQueueDispatcher.$dispatch$lambda$0$FUNCTION_REFERENCE$0.$<bridge-DNN>invoke(){}#internal + 71
at 13 Job.debug.dylib 0x108526a53 kfun:kotlin.Function0#invoke(){}1:0-trampoline + 99
at 14 Job.debug.dylib 0x10863e07b _6f72672e6a6574627261696e732e6b6f746c696e783a6b6f746c696e782d636f726f7574696e65732d636f72652f6f70742f6275696c644167656e742f776f726b2f343465633665383530643563363366302f6b6f746c696e782d636f726f7574696e65732d636f72652f6e617469766544617277696e2f7372632f44697370617463686572732e6b74_knbridge8 + 191
at 15 libdispatch.dylib 0x1037a3ec7 _dispatch_call_block_and_release + 23
at 16 libdispatch.dylib 0x1037bd797 _dispatch_client_callout + 11
at 17 libdispatch.dylib 0x1037b74c7 _dispatch_root_queue_drain + 923
at 18 libdispatch.dylib 0x1037b7dd3 _dispatch_worker_thread2 + 255
at 19 libsystem_pthread.dylib 0x102dceb8f _pthread_wqthread + 227
at 20 libsystem_pthread.dylib 0x102dcd98b start_wqthread + 7
Here's my composeApp/build.gradle.kts:
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidApplication)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
kotlin("plugin.serialization") version "2.1.10"
}
kotlin {
androidTarget {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}
sourceSets {
androidMain.dependencies {
implementation(compose.preview)
implementation(libs.androidx.activity.compose)
implementation("io.ktor:ktor-client-cio:3.1.2")
implementation("io.ktor:ktor-client-logging:3.1.2")
}
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation("io.github.jan-tennert.supabase:postgrest-kt:3.1.4")
implementation("io.github.jan-tennert.supabase:compose-auth:3.1.4")
implementation("io.ktor:ktor-client-logging:3.1.2")
implementation("io.github.jan-tennert.supabase:auth-kt:3.1.4")
}
iosMain.dependencies {
implementation("io.ktor:ktor-client-darwin:3.1.2")
implementation("io.ktor:ktor-client-logging:3.1.2")
}
}
}
android {
namespace = "org.example.job"
compileSdk = libs.versions.android.compileSdk.get().toInt()
defaultConfig {
applicationId = "org.example.job"
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
versionCode = 1
versionName = "1.0"
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
buildFeatures {
buildConfig = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
dependencies {
implementation(libs.androidx.material3.android)
debugImplementation(compose.uiTooling)
val composeBom = platform("androidx.compose:compose-bom:2025.02.00")
implementation("androidx.compose.material3:material3:1.3.2")
implementation(platform("io.github.jan-tennert.supabase:bom:3.1.4"))
}
I tried to add this in the info.plist, but it doesnt change anything:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Any help to debug this will be greatly appreciated, if you need any more informations don't hesitate to tell me.
- UPDATE -
I've been on differents forums and the official Ktor documentation, and managed to solve my problem. I manually initialized the Darwin engine in my SupabaseService
. I created a KtorHttpClient
in commonMain
which I implemented as an actual function in iosMain
, like this:
package org.example.job.service
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.engine.darwin.*
actual fun createHttpClientEngine(): HttpClientEngine {
return Darwin.create {
configureRequest {
setAllowsCellularAccess(true)
}
}
}
And in my SupabaseService
, in the init I added the client:
lateinit var supabaseClient: SupabaseClient
@OptIn(SupabaseInternal::class)
fun initSupabaseClient(
supabaseUrl: String,
supabaseAnonKey: String
) {
supabaseClient = createSupabaseClient(
supabaseUrl = supabaseUrl,
supabaseKey = supabaseAnonKey,
) {
install(Postgrest)
install(Auth)
httpEngine = createHttpClientEngine()
}
}
I hope it can be helpful for someone else too. :)