{"record":{"id":"4cbb8c10b26faa3f","repo":"microg/GmsCore","slug":"acknowledgepurchaseresponse-purchaseitem-is-null","errorCode":null,"errorMessage":"AcknowledgePurchaseResponse PurchaseItem is null","messagePattern":"AcknowledgePurchaseResponse PurchaseItem is null","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"vending-app/src/main/java/org/microg/vending/billing/core/AcknowledgePurchaseResult.kt","lineNumber":29,"sourceCode":") : 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    }\n}","sourceCodeStart":11,"sourceCodeEnd":36,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/vending-app/src/main/java/org/microg/vending/billing/core/AcknowledgePurchaseResult.kt#L11-L36","documentation":"AcknowledgePurchaseResult.parseFrom throws this NullPointerException when the AcknowledgePurchaseResponse is non-null but its purchaseItem field is null. A well-formed acknowledge/purchase response must carry exactly one purchase item; without it the library cannot build a result, so it fails fast with a descriptive message.","triggerScenarios":"Server returns an AcknowledgePurchaseResponse with failedResponse == null but purchaseItem == null — i.e. an otherwise successful-looking response body that contains no purchase item data.","commonSituations":"Partial or truncated protobuf responses from Google Play/Vending; servers replying OK to an acknowledge for a purchase token that does not exist; outdated microG/vendor implementations returning incomplete payloads.","solutions":["Verify the purchase token passed to acknowledgePurchase is valid and belongs to the current user","Log the raw response bytes and decode to confirm purchaseItem is genuinely absent","Update microG/Play Services so the billing backend returns complete responses","Catch NullPointerException from parseFrom and treat it as a failed acknowledge (RESPONSE_CODE != 0)"],"exampleFix":"// before\nval result = iapCore.acknowledgePurchase(params)\n// after\nval result = try {\n    iapCore.acknowledgePurchase(params)\n} catch (e: NullPointerException) {\n    AcknowledgePurchaseResult(null, mapOf(\"RESPONSE_CODE\" to -1, \"DEBUG_MESSAGE\" to e.message ?: \"\"))\n}","handlingStrategy":"type-guard","validationCode":"if (ack.purchaseItem == null) {\n    // handle missing purchase item before parsing\n}","typeGuard":"fun AcknowledgePurchaseResponse.hasPurchaseItem(): Boolean = this.purchaseItem != null","tryCatchPattern":"try {\n    AcknowledgePurchaseResult.parseFrom(ack)\n} catch (e: NullPointerException) {\n    // map to RESPONSE_CODE failure\n}","preventionTips":["Validate the purchase token exists before acknowledging","Decode and inspect the raw protobuf when purchaseItem is unexpectedly absent","Treat a null purchaseItem as a failed response, not a crash"],"tags":["kotlin","nullpointerexception","billing","protobuf"],"backgroundTag":"empty-response-body","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"}