fix(google): surface query product diagnostics#138
Conversation
Add structured QueryProduct diagnostics for Android product query failures, including Billing response code, debug message, queried product IDs, product type, and empty-result state. Propagate the diagnostics through React Native and MAUI bridges, and document the skipped openiap-google 2.1.3 release as openiap-google 2.1.4.
|
Warning Rate limit exceeded
To continue reviewing without waiting, purchase usage credits in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (7)
📒 Files selected for processing (26)
📝 WalkthroughWalkthroughThis PR enriches Android product-query error handling by threading structured billing diagnostics (response code, debug message, product IDs, type, and empty-list indicators) through the error pipeline from the Billing Client API through platform layers to JavaScript consumers, addressing diagnostic gaps described in issue ChangesEnriched Product Query Error Diagnostics
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request enhances error reporting for Android QueryProduct failures by including detailed diagnostics such as responseCode, debugMessage, productIds, productType, and isEmptyProductList. These changes are implemented across the core Google package, React Native and MAUI libraries, and documentation. Key improvements include structured JSON error serialization using JSONObject and updated TypeScript interfaces to support the new fields. I have no feedback to provide as there were no review comments to assess.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt`:
- Around line 338-382: The ProductQueryType.All branch currently wraps both
openIap.fetchProducts calls in a single try-catch causing any per-kind
OpenIAPError to abort the whole query; change this to isolate each kind's fetch
(ProductQueryType.InApp and ProductQueryType.Subs) with per-kind runCatching/try
and default to an empty list on failure, collect any thrown OpenIAPError(s) but
continue, merge results into byId and return products in skusList order, and
only if the merged result is empty rethrow an OpenIapException(created via
toErrorJson from the captured error or a combined error) so partial successes
are preserved (update handling around openIap.fetchProducts,
ProductQueryType.All, OpenIAPError and OpenIapException accordingly).
In `@packages/google/openiap/src/main/java/dev/hyo/openiap/OpenIapError.kt`:
- Around line 17-30: The base OpenIapError.toJSON currently emits responseCode,
productIds, productType and isEmptyProductList for every error subtype; remove
those four diagnostic fields from the OpenIapError.toJSON map so only generic
fields (code, message, platform, debugMessage) are returned, and add/override
toJSON in QueryProductFailure to merge the base map with the diagnostic fields
(responseCode, productIds, productType, isEmptyProductList) so only
QueryProductFailure serializes them; refer to OpenIapError.toJSON and the
QueryProductFailure class when making the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 687b01b4-6bff-4efc-b233-b90ef84f3122
📒 Files selected for processing (12)
libraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.ktlibraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.ktlibraries/react-native-iap/src/index.tslibraries/react-native-iap/src/utils/error.tslibraries/react-native-iap/src/utils/errorMapping.tspackages/docs/src/pages/docs/errors.tsxpackages/docs/src/pages/docs/updates/releases.tsxpackages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/main/java/dev/hyo/openiap/OpenIapError.ktpackages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.ktpackages/google/openiap/src/play/java/dev/hyo/openiap/helpers/ProductManager.ktpackages/google/openiap/src/test/java/dev/hyo/openiap/OpenIapErrorTest.kt
|
@coderabbitai review |
|
/gemini review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Code Review
This pull request introduces enhanced error diagnostics for Android QueryProduct failures, adding detailed fields such as responseCode, productIds, and productType to error objects across the Google, MAUI, and React Native libraries. It also refactors the React Native Android implementation to use a new collectAllQueryProducts helper and updates documentation to enforce a policy where openiap-versions.json only tracks core platform versions. Review feedback recommends parallelizing the sequential network requests in the new Android helper using coroutines to improve performance and highlights a discrepancy between the PR description and the manual removal of the maui key from the version manifest.
There was a problem hiding this comment.
Pull request overview
This PR improves Android QueryProduct failure observability by carrying Google Billing diagnostics through the openiap-google (Play + Horizon) query paths, then plumbing those diagnostics through the React Native and MAUI Android bridges, and documenting the new fields.
Changes:
- Add a diagnostic-carrying
QueryProducterror variant and populate it from BillingResult details in Play/Horizon query flows. - Propagate the new diagnostic fields through the React Native error types + Android bridge (including new helper + tests).
- Update docs/release notes and clarify version-manifest ownership/scope; adjust MAUI release workflow to read the NuGet version from the csproj.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/kit/convex/_generated/api.d.ts | Regenerated Convex API typings to include utils/currency. |
| packages/google/openiap/src/test/java/dev/hyo/openiap/OpenIapErrorTest.kt | Adds tests asserting QueryProduct diagnostic serialization behavior. |
| packages/google/openiap/src/play/java/dev/hyo/openiap/OpenIapModule.kt | Surfaces BillingResult diagnostics when product queries fail in Play flow. |
| packages/google/openiap/src/play/java/dev/hyo/openiap/helpers/ProductManager.kt | Converts Play query failures to OpenIapError.QueryProduct(...) with diagnostics. |
| packages/google/openiap/src/main/java/dev/hyo/openiap/OpenIapError.kt | Makes toJSON() overridable and adds diagnostic-carrying QueryProduct failure type. |
| packages/google/openiap/src/horizon/java/dev/hyo/openiap/OpenIapModule.kt | Surfaces BillingResult diagnostics when product queries fail in Horizon flow. |
| packages/docs/src/pages/docs/updates/releases.tsx | Updates release notes entry to openiap-google 2.1.4 and mentions new diagnostics. |
| packages/docs/src/pages/docs/errors.tsx | Documents Android QueryProduct diagnostics fields and usage guidance. |
| packages/docs/openiap-versions.json | Removes maui key; keeps only spec/google/apple in docs copy. |
| openiap-versions.json | Removes maui key; keeps only spec/google/apple in root manifest. |
| libraries/react-native-iap/src/utils/errorMapping.ts | Extends purchase error types/mapping to include new query diagnostics fields. |
| libraries/react-native-iap/src/utils/error.ts | Extends parsed error shape to include new query diagnostics fields. |
| libraries/react-native-iap/src/index.ts | Wraps fetchProducts errors into structured PurchaseError including diagnostics. |
| libraries/react-native-iap/android/src/test/java/com/margelo/nitro/iap/ProductQueryHelpersTest.kt | Adds unit tests for new “All query” product collection helper behavior. |
| libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/ProductQueryHelpers.kt | Introduces helper to aggregate InApp+Subs queries with partial-success behavior. |
| libraries/react-native-iap/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt | Uses helper for All queries and serializes diagnostics via error.toJSON(). |
| libraries/maui-iap/CLAUDE.md | Clarifies the MAUI symlink purpose for native version manifest keys. |
| libraries/maui-iap/android/openiap/src/main/java/dev/hyo/openiap/maui/OpenIapMauiModule.kt | Adds diagnostic fields to encoded error payloads. |
| knowledge/internal/06-git-deployment.md | Documents that version manifest is only for spec/google/apple (no framework keys). |
| knowledge/internal/04-platform-packages.md | Updates internal docs example for current manifest schema. |
| CLAUDE.md | Clarifies openiap-versions.json scope (only spec/google/apple). |
| .github/workflows/release-maui.yml | Reads/bump MAUI version from OpenIap.Maui.csproj instead of openiap-versions.json. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request improves Android error diagnostics by including Google Play Billing response codes, debug messages, and product details in QueryProduct failures. It updates the OpenIapError hierarchy to support these diagnostics and propagates them through the Android and React Native layers. I have flagged a potential breaking change regarding the modification of the QueryProduct error type, which may require a major version bump instead of the current patch release.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request enhances the PurchaseError model across all platforms by adding diagnostic fields for Android QueryProduct failures, including responseCode, productIds, productType, and isEmptyProductList. It updates the GraphQL schema, generated types, and documentation accordingly. Feedback identifies a compilation error caused by a typo in OpenIapError, a breaking change in Kotlin error type checking for QueryProduct, and a missing constant reference. Additionally, a type mismatch was noted between the GDScript documentation and its implementation.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces detailed diagnostic fields—responseCode, productIds, productType, and isEmptyProductList—to the PurchaseError type across the entire SDK, including the GraphQL schema, documentation, and all framework libraries. The Android implementation in openiap-google is updated to populate these fields during product queries, and react-native-iap now utilizes a new concurrent fetching helper. Feedback was provided regarding a thread-safety vulnerability in the OpenIapError.QueryProduct singleton, where storing diagnostic state in a volatile property could result in race conditions during concurrent queries.
|
/gemini review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request enhances the PurchaseError model by adding diagnostic fields—responseCode, productIds, productType, and isEmptyProductList—across all platform libraries and the GraphQL schema to improve Android error reporting. The React Native Android implementation was refactored to fetch InApp and Subs products concurrently, and error handling was unified under the OpenIapError naming convention. Documentation and release notes were updated accordingly. Feedback identified a potential race condition in the Android native QueryProduct error object due to its stateful singleton design, recommending a transition to a class-based implementation for better thread safety.
I am having trouble creating individual review comments. Click here to see my feedback.
packages/google/openiap/src/main/java/dev/hyo/openiap/OpenIapError.kt (163-222)
Using a stateful singleton for QueryProduct introduces a potential race condition. If two product queries fail on different threads concurrently, one thread's call to withDiagnostics could overwrite the diagnostic data of another before it's fully processed.
While the current usage with BillingClient callbacks on the main thread might prevent this, it makes the design fragile and reliant on external guarantees. Any future use of this error from a multi-threaded context could lead to subtle bugs.
To ensure thread safety and a more robust design, consider changing QueryProduct from an object to a class or data class. This would be a breaking change, but it would eliminate the risks associated with a stateful singleton.
Example of a safer implementation:
data class QueryProduct(
val responseCode: Int? = null,
override val debugMessage: String? = null,
val productIds: List<String> = emptyList(),
val productType: String? = null,
val isEmptyProductList: Boolean? = null,
) : OpenIapError() {
override val code = ErrorCode.QueryProduct.rawValue
override val message = "Failed to query product"
override fun toJSON(): Map<String, Any?> {
return super.toJSON() + mapOf(
"responseCode" to responseCode,
"productIds" to productIds,
"productType" to productType,
"isEmptyProductList" to isEmptyProductList,
)
}
}This would require updating call sites to instantiate QueryProduct(...) instead of using the singleton. If a breaking change is not an option for this patch release, I'd recommend adding a prominent warning in the KDoc for withDiagnostics about the thread-safety implications.
There was a problem hiding this comment.
Code Review
This pull request introduces enhanced diagnostic reporting for Android QueryProduct failures by adding fields like responseCode, productIds, productType, and isEmptyProductList to the PurchaseError model across all supported platforms (Kotlin, Swift, C#, Dart, TypeScript). It also includes a new collectAllQueryProducts helper in the React Native IAP library to handle concurrent product queries and updates documentation and version manifests to reflect these changes. The review comments were filtered to remove non-actionable validation feedback, keeping only the request for a missing import.
Summary
Issue
Closes #137
Notes
Validation
Summary by CodeRabbit
Bug Fixes
Documentation