{"record":{"id":"0e54f3354b9c2017","repo":"microg/GmsCore","slug":"response-is-null","errorCode":null,"errorMessage":"response is null","messagePattern":"response is null","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"vending-app/src/main/java/org/microg/vending/billing/core/AcknowledgePurchaseResult.kt","lineNumber":17,"sourceCode":"package org.microg.vending.billing.core\n\nimport org.microg.vending.billing.proto.AcknowledgePurchaseResponse\n\nclass AcknowledgePurchaseResult(\n    val purchaseItem: PurchaseItem? = null,\n    resultMap: Map<String, Any> = mapOf(\n        \"RESPONSE_CODE\" to 0,\n        \"DEBUG_MESSAGE\" to \"\"\n    )\n) : IAPResult(resultMap) {\n    companion object {\n        fun parseFrom(\n            response: AcknowledgePurchaseResponse?\n        ): AcknowledgePurchaseResult {\n            if (response == null) {\n                throw NullPointerException(\"response is null\")\n            }\n            if (response.failedResponse != null) {\n                return AcknowledgePurchaseResult(\n                    null,\n                    mapOf(\n                        \"RESPONSE_CODE\" to (response.failedResponse?.statusCode ?: 0),\n                        \"DEBUG_MESSAGE\" to (response.failedResponse?.msg ?: \"\")\n                    )\n                )\n            }\n            if (response.purchaseItem == null) {\n                throw NullPointerException(\"AcknowledgePurchaseResponse PurchaseItem is null\")\n            }\n            if (response.purchaseItem?.purchaseItemData?.size != 1)\n                throw IllegalStateException(\"AcknowledgePurchaseResult purchase item count != 1\")\n            return AcknowledgePurchaseResult(parsePurchaseItem(response.purchaseItem!!).getOrNull(0))\n        }\n    }","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/vending-app/src/main/java/org/microg/vending/billing/core/AcknowledgePurchaseResult.kt#L1-L35","documentation":"AcknowledgePurchaseResult.parseFrom throws this NullPointerException when the raw AcknowledgePurchaseResponse passed to it is null. The library treats a missing protobuf response as a programming/transport invariant violation rather than a normal IAP failure, so it fails fast instead of building a result object from nothing.","triggerScenarios":"Calling AcknowledgePurchaseResult.parseFrom(null), typically when the enclosing GoogleApiResponse has payload == null or payload.acknowledgePurchaseResponse == null (e.g. the Play Billing/Vending server returned an empty or malformed response body that decoded to no acknowledgePurchaseResponse).","commonSituations":"Users on broken/modified microG or Play Services setups where the Google Play billing endpoint returns an empty payload; apps calling acknowledgePurchase() against a corrupted protobuf response; unit tests passing null directly.","solutions":["Check the enclosing response payload before calling parseFrom: only call it when response.payload?.acknowledgePurchaseResponse != null","Inspect the raw network response (enable logging in HttpClient) to see why the server omitted acknowledgePurchaseResponse","Ensure Google Play / microG services are up to date so the server returns a well-formed response","Wrap the call in try-catch for NullPointerException and surface a friendly billing-unavailable error"],"exampleFix":"// before\nval result = AcknowledgePurchaseResult.parseFrom(response.payload?.acknowledgePurchaseResponse)\n// after\nval ack = response.payload?.acknowledgePurchaseResponse\nval result = if (ack != null) AcknowledgePurchaseResult.parseFrom(ack) else AcknowledgePurchaseResult(null, mapOf(\"RESPONSE_CODE\" to -1, \"DEBUG_MESSAGE\" to \"empty acknowledge response\"))","handlingStrategy":"type-guard","validationCode":"val ack = response.payload?.acknowledgePurchaseResponse\nrequireNotNull(ack) { \"acknowledgePurchaseResponse missing from payload\" }","typeGuard":"fun AcknowledgePurchaseResponse?.isValid(): Boolean = this != null","tryCatchPattern":"try {\n    AcknowledgePurchaseResult.parseFrom(response.payload?.acknowledgePurchaseResponse)\n} catch (e: NullPointerException) {\n    // treat as failed acknowledge\n}","preventionTips":["Never pass response.payload?.acknowledgePurchaseResponse directly; null-check first","Log the raw payload when acknowledgePurchaseResponse is absent","Keep microG/Play Services updated to avoid empty server payloads"],"tags":["kotlin","nullpointerexception","billing","protobuf"],"backgroundTag":"null-argument","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}