{"record":{"id":"bdf718b19ea0e5b6","repo":"microg/GmsCore","slug":"api-unavailable","errorCode":null,"errorMessage":"API unavailable","messagePattern":"API unavailable","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"play-services-core/src/main/kotlin/com/google/android/gms/common/GoogleCertificatesImpl.kt","lineNumber":69,"sourceCode":"            query?.callingPackage == null -> false\n            query.certData != null -> {\n                isGooglePackage(query.callingPackage, query.certData) || (pm != null && pm.isPlatformCertificate(query.certData))\n            }\n            pm != null -> pm.getExtendedPackageInfo(query.callingPackage).isGoogleOrPlatformPackage\n            else -> false\n        }\n    }\n\n    override fun isPackageGoogleOrPlatformSigned(query: GoogleCertificatesLookupQuery): GoogleCertificatesLookupResponse {\n        return certificateLookup(query, true)\n    }\n\n    override fun isPackageGoogleOrPlatformSignedAvailable(): Boolean {\n        return true\n    }\n\n    override fun queryPackageSigned(query: GoogleCertificatesLookupQuery): GoogleCertificatesLookupResponse {\n        if (!isFineGrainedPackageVerificationAvailable) throw IllegalStateException(\"API unavailable\")\n        return certificateLookup(query, false)\n    }\n\n    override fun isFineGrainedPackageVerificationAvailable(): Boolean {\n        return true\n    }\n\n    private fun certificateLookup(query: GoogleCertificatesLookupQuery, allowPlatform: Boolean): GoogleCertificatesLookupResponse {\n        val context = query.context\n            ?: return GoogleCertificatesLookupResponse(false, \"context is null\", 5, 1)\n        val packageManager = context.packageManager\n            ?: return GoogleCertificatesLookupResponse(false, \"context has no package manager\", 5, 1)\n        val callingPackage = query.callingPackage\n            ?: return GoogleCertificatesLookupResponse(false, \"callingPackage is null\", 5, 1)\n        val packageInfo = packageManager.getExtendedPackageInfo(callingPackage)\n        if (!packageInfo.isInstalled)\n            return GoogleCertificatesLookupResponse(false, \"callingPackage not found\", 4, 1)\n        return if (packageInfo.isGooglePackage || (allowPlatform && packageInfo.isPlatformPackage)) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-core/src/main/kotlin/com/google/android/gms/common/GoogleCertificatesImpl.kt#L51-L87","documentation":"GoogleCertificatesImpl.queryPackageSigned throws IllegalStateException(\"API unavailable\") when fine-grained package signature verification is not available. The check delegates to isFineGrainedPackageVerificationAvailable, so this guard fires whenever that capability query returns false.","triggerScenarios":"Calling queryPackageSigned(GoogleCertificatesLookupQuery) while isFineGrainedPackageVerificationAvailable returns false — in upstream Play services this happens when the Play services version lacks the fine-grained verification API; in microG it is normally always true, so hitting this means an unexpected state or modified build.","commonSituations":"Apps probing Google certificate verification on devices with mismatched or outdated Play services / microG builds, or forked builds where the capability override was changed to false.","solutions":["Check isFineGrainedPackageVerificationAvailable (or isPackageGoogleOrPlatformSignedAvailable) before calling queryPackageSigned","Update microG to a current build where the fine-grained verification API is implemented","Fall back to the non-fine-grained lookup path when the capability is unavailable","Catch IllegalStateException around the lookup and degrade gracefully"],"exampleFix":"// before\nval result = certs.queryPackageSigned(query)\n// after\nif (!certs.isFineGrainedPackageVerificationAvailable) {\n    throw IllegalStateException(\"fine-grained verification not available\")\n}\nval result = certs.queryPackageSigned(query)","handlingStrategy":"type-guard","validationCode":"if (!certs.isFineGrainedPackageVerificationAvailable) {\n    throw IllegalStateException(\"fine-grained verification unavailable\")\n}","typeGuard":"fun GoogleCertificatesLookup.canQueryFineGrained(): Boolean =\n    isPackageGoogleOrPlatformSignedAvailable && isFineGrainedPackageVerificationAvailable","tryCatchPattern":"try {\n    val result = certs.queryPackageSigned(query)\n} catch (e: IllegalStateException) {\n    // fall back to coarse lookup\n}","preventionTips":["Check capability booleans before invoking fine-grained APIs","Keep microG updated to builds implementing the verification API","Design fallback paths for older Play services versions"],"tags":["android","play-services","certificates"],"backgroundTag":"feature-not-enabled","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"}