Skip to content

fix(payment): return correct result shape from updatePaymentCollections and workflow - #16777

Open
coderlucifer wants to merge 2 commits into
medusajs:developfrom
coderlucifer:fix/payment-collection-result-type
Open

fix(payment): return correct result shape from updatePaymentCollections and workflow#16777
coderlucifer wants to merge 2 commits into
medusajs:developfrom
coderlucifer:fix/payment-collection-result-type

Conversation

@coderlucifer

Copy link
Copy Markdown

What

Fix result type mismatch in updatePaymentCollections selector overload and createOrUpdateOrderPaymentCollectionWorkflow.

Fixes #16751

Why

The createOrUpdateOrderPaymentCollectionWorkflow declares PaymentCollectionDTO[] as its result type, but:

  1. The update branch returns a single PaymentCollectionDTO instead of an array — because updatePaymentCollections in the Payment Module checks Array.isArray(data) (the update payload, which is always an object) instead of checking the first argument (idOrSelector). This causes the selector overload to always serialize result[0] instead of the full result array.

  2. The no-op branch returns undefined instead of [] — when neither the create nor update branch executes (e.g., zero pending amount with no existing collection), the transform returns undefined.

This silently breaks any caller relying on the declared array contract (e.g., result[0].id).

How

packages/modules/payment/src/services/payment-module.ts (L284)

Changed the serialization guard from:

- Array.isArray(data) ? result : result[0]
+ isString(idOrSelector) ? result[0] : result

isString(idOrSelector) correctly returns a single DTO for the ID overload and an array for the selector overload, matching the declared type signatures.

packages/core/core-flows/src/order/workflows/create-or-update-order-payment-collection.ts (L198)

Added || [] fallback:

- updatedPaymentCollections || createdPaymentCollection
+ updatedPaymentCollections || createdPaymentCollection || []

Ensures the workflow always returns PaymentCollectionDTO[] as declared.

Testing

  • Added 2 integration tests to packages/modules/payment/integration-tests/__tests__/services/payment-module/index.spec.ts:
    • "should return an array when updating via selector" — verifies the selector overload returns PaymentCollectionDTO[]
    • "should return a single DTO when updating via string ID" — verifies the ID overload returns PaymentCollectionDTO
  • Verified the fix logic in isolation against the original buggy logic, confirming the old code always returned result[0] regardless of call style

…ns and workflow

The selector overload of updatePaymentCollections checked Array.isArray(data) to
decide between single/array result, but data is always an object. Changed to check
isString(idOrSelector) to correctly return an array for selector calls.

Also normalized the createOrUpdateOrderPaymentCollectionWorkflow to return [] instead
of undefined when neither branch executes.

Fixes medusajs#16751
@coderlucifer
coderlucifer requested a review from a team as a code owner September 10, 2026 09:44
@changeset-bot

changeset-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 34a5a62

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 83 packages
Name Type
@medusajs/payment Patch
@medusajs/core-flows Patch
@medusajs/medusa Patch
@medusajs/test-utils Patch
integration-tests-http Patch
@medusajs/loyalty-plugin Patch
@medusajs/medusa-oas-cli Patch
@medusajs/analytics Patch
@medusajs/api-key Patch
@medusajs/auth Patch
@medusajs/caching Patch
@medusajs/cart Patch
@medusajs/currency Patch
@medusajs/customer Patch
@medusajs/file Patch
@medusajs/fulfillment Patch
@medusajs/index Patch
@medusajs/inventory Patch
@medusajs/link-modules Patch
@medusajs/locking Patch
@medusajs/notification Patch
@medusajs/order Patch
@medusajs/pricing Patch
@medusajs/product Patch
@medusajs/promotion Patch
@medusajs/rbac Patch
@medusajs/region Patch
@medusajs/sales-channel Patch
@medusajs/search Patch
@medusajs/settings Patch
@medusajs/stock-location Patch
@medusajs/store Patch
@medusajs/tax Patch
@medusajs/translation Patch
@medusajs/user Patch
@medusajs/workflow-engine-inmemory Patch
@medusajs/workflow-engine-redis Patch
@medusajs/search-postgres Patch
@medusajs/draft-order Patch
@medusajs/oas-github-ci Patch
@medusajs/cache-inmemory Patch
@medusajs/cache-redis Patch
@medusajs/event-bus-local Patch
@medusajs/event-bus-redis Patch
@medusajs/analytics-local Patch
@medusajs/analytics-posthog Patch
@medusajs/auth-emailpass Patch
@medusajs/auth-github Patch
@medusajs/auth-google Patch
@medusajs/auth-oidc Patch
@medusajs/caching-redis Patch
@medusajs/file-local Patch
@medusajs/file-s3 Patch
@medusajs/fulfillment-manual Patch
@medusajs/locking-postgres Patch
@medusajs/locking-redis Patch
@medusajs/notification-local Patch
@medusajs/notification-sendgrid Patch
@medusajs/payment-stripe Patch
@medusajs/framework Patch
@medusajs/instantsearch-adapter Patch
@medusajs/js-sdk Patch
@medusajs/modules-sdk Patch
@medusajs/orchestration Patch
@medusajs/query Patch
@medusajs/types Patch
@medusajs/utils Patch
@medusajs/workflows-sdk Patch
create-medusa-app Patch
@medusajs/http-types-generator Patch
@medusajs/cli Patch
@medusajs/deps Patch
@medusajs/eslint-plugin Patch
@medusajs/telemetry Patch
@medusajs/admin-bundler Patch
@medusajs/admin-sdk Patch
@medusajs/admin-shared Patch
@medusajs/admin-vite-plugin Patch
@medusajs/dashboard Patch
@medusajs/icons Patch
@medusajs/toolbox Patch
@medusajs/ui-preset Patch
@medusajs/ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@medusa-os-bot

medusa-os-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

Thanks for the contribution! Initial automated review looks good.

This PR fixes two related type-contract violations in the payment module and the order payment-collection workflow. 1. packages/modules/payment/src/services/payment-module.ts: The updatePaymentCollections implementation used Array.isArray(data) to choose between returning a single DTO or an array. Since data is the update payload (always a plain object, never an array), this guard was always false, causing the selector overload to incorrectly return only result[0] instead of the declared PaymentCollectionDTO[]. The fix switches to isString(idOrSelector), which correctly returns a single DTO for the ID overload and a full array for the selector overload. isString is already imported and used earlier in the same method. 2. packages/core/core-flows/src/order/workflows/create-or-update-order-payment-collection.ts: The workflow's final transform could return undefined when neither the create nor the update branch executed. The || [] fallback ensures the result is always PaymentCollectionDTO[] as declared. The PR includes a changeset (patch bump for @medusajs/payment and @medusajs/core-flows, fix(...) format) and two integration tests that directly verify the selector-overload array return and the string-ID single-DTO return against the existing pay-col-id-2 fixture. The fix is narrowly scoped to the reported issue, conventions are followed, and no security or performance concerns were found.

Triggered by: new PR opened

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Order payment-collection workflow returns object or undefined despite array result type

1 participant