What does Transaction.RefundRequestError.duplicateRequest mean?
Transaction.RefundRequestError.duplicateRequest means the App Store has already received a refund request for this In-App Purchase.
Quick facts#
| Error | Transaction.RefundRequestError.duplicateRequest |
| Where | StoreKit 2, Swift (Transaction.beginRefundRequest) |
| Available since | iOS 15.0, iPadOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, visionOS 1.0 |
| What the vendor says | The App Store has already received a refund request for this In-App Purchase. |
Cause#
- Apple says StoreKit returns this error when the App Store already holds a refund request for the transaction and the decision is still pending, was denied or was approved.
- The person (or your code) called
beginRefundRequestfor a transaction that already has a request. Sending it again cannot change the outcome. - Apple suggests checking the transaction's refund state before you call the method, to see whether the App Store has already refunded it.
Fix#
- Before you offer a refund request, check the transaction's
revocationDateandrevocationReason. If the App Store has already refunded the purchase there is nothing to request. - Tell the person a request already exists, and that Apple makes the decision.
- Do not call the method again for the same transaction.
- Test refund requests in the sandbox or in Xcode first, as Apple's refund testing guide describes.
Example#
Swift
import StoreKit
import UIKit
// A second request for the same transaction cannot work: say so, and stop.
@MainActor
func requestRefund(productID: String, in scene: UIWindowScene) async {
guard let result = await Transaction.latest(for: productID), case .verified(let transaction) = result else { return }
// Apple suggests checking the refund state first: a revoked transaction is already refunded.
if transaction.revocationDate != nil {
print("The App Store already refunded this purchase")
return
}
do {
let status = try await transaction.beginRefundRequest(in: scene)
print("Refund request status: \(status)")
} catch Transaction.RefundRequestError.duplicateRequest {
print("A refund request for this purchase already exists; Apple decides it")
} catch {
print("Refund request failed: \(error)")
}
}Compile-checked: npm run check:snippets type-checks this snippet with swiftc against the Apple SDK (macOS target, checked 2026-10-03).
How the RevenueDot SDK reports it#
The RevenueDot purchases-ios fork wraps this in beginRefundRequest(forEntitlement:). It logs a message for duplicateRequest and reports the failure as ErrorCode.beginRefundRequestError (code 31).
Related#
- What does StoreKitError.unknown mean?
- What does storeProblemError (code 2) mean in the purchases SDK?
- What does VerificationError.invalidSignature mean in StoreKit 2?
- Apple: Testing refund requests
Source#
- Apple: Transaction.RefundRequestError.duplicateRequest
- Apple: Transaction.RefundRequestError
- RevenueDot purchases-ios: SK2BeginRefundRequestHelper.swift
Checked: 2026-10-03