Skip to content

[BUG] Failed event uploads are not retained for retry, causing missing purchase attribution #514

Description

@hcz1

New issue checklist

  • I have read the documentation and this doesn't appear to be expected behavior
  • I have searched existing issues and this is not a duplicate
  • I have tried to reproduce the issue in a minimal sample project I can share

Affected user

Affected sandbox user details can be shared privately via Superwall support. User and transaction identifiers are omitted from this public issue.

When did it happen?

28 August 2026, approximately 08:55:44-08:55:49 UTC (09:55:44-09:55:49 BST). A later successful comparison purchase occurred at 09:15:41 UTC.

SuperwallKit version

4.16.3

Last SDK version that worked

No known SDK-version regression. The same 4.16.3 build later delivered and attributed a purchase successfully.

iOS version(s)

iOS 18.7.8

Xcode version

Xcode 26.3 (17C529)

Installation method

Swift Package Manager

Devices/simulators affected

Physical iPhone 15 Pro Max. Development-signed build installed through Xcode; Apple sandbox account. Not TestFlight or a simulator.

Reproducible in the example app?

Haven't tried

How is the SDK set up?

  • Native iOS app using SuperwallKit 4.16.3 via Swift Package Manager.
  • Superwall is configured once and handles purchases and subscription status itself. No custom PurchaseController or RevenueCat integration.
  • Paywalls are presented through register(placement:); purchases use the native Apple payment sheet.
  • Anonymous Superwall identity; no call to identify(userId:).
  • eventTrackingBehavior is .all.
  • Development-signed app installed through Xcode on a physical iPhone, using an Apple sandbox account. Not TestFlight or a local StoreKit configuration.

Describe the bug

Summary

A sandbox purchase completed through a Superwall paywall, but its transaction_complete event existed only in the device's Superwall Core Data store and was missing from the server-side SDK event stream. Apple subscription notifications arrived, but the revenue events lacked user, placement, paywall and campaign attribution.

The dashboard reported that Superwall could not tie the event to an identified app user and that the transaction_complete SDK event was missing.

Observations

  • On 28 August 2026, Apple recorded the affected transaction at 08:55:44 UTC.
  • The device stored transaction_complete at 08:55:49 UTC, with preceding paywall_open and transaction_start events. The purchase event contained the matching Apple transaction ID, app account token, anonymous Superwall alias and paywall/placement/campaign metadata.
  • The matching SDK event was absent from the server data when checked. Other SDK events from the affected period were also missing.
  • NordVPN was connected during the affected session. Disconnecting it appeared to resolve the problem: a later purchase at 09:15:41 UTC delivered transaction_complete at 09:15:45 UTC and subsequently became fully attributed.
  • The earlier missing purchase events were still absent during subsequent checks.

Expected vs actual

Expected: while tracking is enabled, purchase events affected by retryable network failures should be retained and replayed after connectivity returns, including after an app restart.

Actual: new events resumed, but the earlier locally recorded purchase events did not recover during our checks.

The failing HTTP status/URLSession error was not captured. NordVPN is a suspected trigger, not a confirmed root cause; Threat Protection/DNS filtering has not been isolated from tunnel or routing problems. The queue failure path described below is consistent with these observations, but has not been confirmed with an isolated regression test.

Steps to reproduce

Observed sequence in the affected physical-device sandbox session (not yet reproduced in the SDK example app):

  1. Configure Superwall with its default purchase handling and all event tracking enabled.
  2. Connect NordVPN and open a Superwall paywall.
  3. Complete a sandbox purchase through the native Apple payment sheet.
  4. Compare the locally recorded SDK events with the server-side SDK stream and Apple subscription notifications. In our session, the local transaction_complete existed but the server copy was missing.
  5. Disconnect NordVPN and reopen the app. New uploads resumed, but earlier missing purchase events remained absent during subsequent checks.

A deterministic regression test is still needed: make the events transport exhaust its retries, restore connectivity, then test delivery both in the same process and after recreating the queue/restarting the app. This proposed test has not been run.

Debug logs

No debug log was captured for the failing request, so its HTTP status and URLSession error are unknown.

Debug logging enabled later showed a successful POST to https://collector.superwall.me/api/v1/events, and the corresponding event was received server-side. This confirms later recovery for new events, not the exact cause of the earlier failure.

User identifiers, transaction identifiers and raw event payloads are omitted from this public report and can be shared privately with Superwall support.

Other information

Source review (4.16.3)

  • PlacementsQueue.swift: pending events are held in memory. flushInternal removes entries before starting the send task, without receiving a delivery acknowledgement or restoring the batch on failure.
  • Network.swift: sendEvents returns Void; its catch block logs the error without returning failure to the queue.
  • Task+Retrying.swift: request-level retries are finite.
  • Tracking.swift: the Core Data history is separate from the upload queue; the inspected queue does not replay that history after failed delivery.
  • TransactionManager.swift: transaction completion explicitly flushes the queue, so waiting for the normal periodic flush alone does not address recovery.

The relevant queue, network sender and retry files were also checked at develop commit 15647e1 and were unchanged from 4.16.3. This is source analysis, not a completed regression test.

Related reports and documentation

Recovery question

Is there an existing supported mechanism that persists transaction_complete and replays it after retries are exhausted? If not, could the SDK retain pending events until acknowledged, with bounded retry/retention policies, original event IDs for deduplication, and correct opt-out/identity-reset handling?

This request concerns recovery when connectivity is restored, not bypassing user-selected network filtering.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions