supabasekotlin-multiplatformktorcompose-multiplatform

Not able to connect to Supabase in iOS simulator


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.


Solution

  • - 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. :)