Skip to content

insertInvoiceRecord overwrites custom fields - missing { merge: true } (same as fixed #169) #724

@Yannholo

Description

@Yannholo

Bug report

Extension name: firestore-stripe-payments

Describe the bug

The insertInvoiceRecord function in utils.ts uses .set(invoice) without { merge: true }, which overwrites any custom fields added to invoice documents. This is the same bug that was fixed for products/prices in PR #170 (resolving #169), but was not applied to invoices.

Affected code

https://github.com/invertase/stripe-firebase-extensions/blob/next/firestore-stripe-payments/functions/src/utils.ts#L322-L332

// Current code (line ~327):
await customersSnap.docs[0].ref
  .collection('subscriptions')
  .doc(invoice.subscription as string)
  .collection('invoices')
  .doc(invoice.id)
  .set(invoice);  // ❌ Missing { merge: true }

Inconsistency with other functions

Other functions in the same file correctly use { merge: true }:

Function Code Status
createProductRecord .set(productData, { merge: true }) ✅ Fixed in #170
insertPriceRecord .set(priceData, { merge: true }) ✅ Fixed in #170
insertPaymentRecord .set(payment, { merge: true }) ✅ Correct
insertInvoiceRecord .set(invoice) Missing
manageSubscriptionStatusChange .set(subscriptionData) Also missing

To reproduce

  1. Set up an Eventarc trigger on invoice document writes
  2. In your handler, add a custom field to the invoice document (e.g., mac_status: "processed")
  3. Wait for Stripe to send another webhook for the same invoice (e.g., invoice.paid followed by invoice.payment_succeeded)
  4. Observe that your custom field is erased

Expected behavior

Custom fields added to invoice documents should be preserved when the extension updates the document with new Stripe data (same behavior as products/prices after #170 fix).

Actual behavior

The entire invoice document is overwritten, erasing any custom fields. This is particularly problematic because Stripe sends multiple webhook events for the same invoice (invoice.paid, invoice.payment_succeeded, invoice.payment_action_required, etc.), each triggering a full overwrite.

Impact

This makes it impossible to use the invoice document itself to track processing state, forcing users to maintain separate collections for idempotency tracking.

Suggested fix

- .set(invoice);
+ .set(invoice, { merge: true });

Also consider applying the same fix to manageSubscriptionStatusChange for consistency.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions