{"record":{"id":"c01f1d8ccd047880","repo":"microg/GmsCore","slug":"collision-in-hash-string-can-t-use-sms-retriever","errorCode":null,"errorMessage":"Collision in hash string, can't use SMS Retriever API","messagePattern":"Collision in hash string, can't use SMS Retriever API","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"play-services-auth-api-phone/core/src/main/kotlin/org/microg/gms/auth/phone/SmsRetrieverCore.kt","lineNumber":101,"sourceCode":"                context.registerReceiver(smsBroadcastReceiver, intentFilter)\n            }\n        }\n    }\n\n    private suspend fun ensureReady(permissions: Array<String>): Boolean {\n        if (SDK_INT < 19) throw RuntimeException(\"Version not supported\")\n        if (!ensurePermission(permissions)) return false\n        configureBroadcastListenersIfNeeded()\n        return true\n    }\n\n    suspend fun startSmsRetriever(packageName: String) {\n        val appHashString = getHashString(packageName)\n\n        if (!ensureReady(arrayOf(RECEIVE_SMS)))\n            throw RuntimeException(\"Initialization failed\")\n        if (anyOtherPackageHasHashString(packageName, appHashString))\n            throw RuntimeException(\"Collision in hash string, can't use SMS Retriever API\")\n        if (requests.values.any { it.packageName == packageName && it.appHashString == appHashString && it.type == RETRIEVER })\n            throw RuntimeException(\"App already listening\")\n\n        val request = SmsRetrieverRequest(\n            id = requestIdCounter.incrementAndGet(),\n            type = RETRIEVER,\n            packageName = packageName,\n            appHashString = appHashString,\n            timeoutPendingIntent = getTimeoutPendingIntent(context, packageName)\n        )\n        requests[request.id] = request\n        alarmManager.set(AlarmManager.RTC, request.creation + TIMEOUT, request.timeoutPendingIntent)\n    }\n\n    suspend fun startWithConsentPrompt(packageName: String, senderPhoneNumber: String?) {\n        if (!ensureReady(arrayOf(RECEIVE_SMS, READ_CONTACTS)))\n            throw RuntimeException(\"Initialization failed\")\n        if (requests.values.any { it.packageName == packageName && it.senderPhoneNumber == senderPhoneNumber && it.type == USER_CONSENT })","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-auth-api-phone/core/src/main/kotlin/org/microg/gms/auth/phone/SmsRetrieverCore.kt#L83-L119","documentation":"startSmsRetriever throws this when anyOtherPackageHasHashString(packageName, appHashString) returns true: another installed package computes the same 11-character SMS Retriever hash (derived from package name + signing certificate SHA-256). Because OTP codes are broadcast to whichever app holds the matching hash, a hash collision would let another app intercept your SMS codes, so the library refuses to start.","triggerScenarios":"Two installed apps signed with the same certificate and sharing the same package-name/hash derivation, or a test/debug-signed duplicate build of your app installed alongside the real app.","commonSituations":"Debug and release builds signed with the same debug key installed side by side; clone/parallel-space apps; re-signed APKs installed on the same device during development.","solutions":["Uninstall the conflicting app that shares the same hash string (check other installed builds of your app)","Sign your app with a unique release keystore so its hash differs from other packages","Rename the applicationId of duplicate test builds to avoid hash overlap","Remove clone/parallel-app wrappers that re-sign packages with a shared key"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { core.startSmsRetriever(pkg) } catch (e: RuntimeException) { if (e.message?.startsWith(\"Collision in hash string\") == true) showHashConflictUi() else throw e }","preventionTips":["Sign release and debug builds with distinct keys","Avoid installing clone/duplicate builds of the same app on test devices","Use unique applicationIds per build variant"],"tags":["android","sms-retriever","hash-collision","app-signing"],"backgroundTag":"invalid-state-transition","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}