Skip to content

Fix product list crash with orphaned sales channel references#14961

Open
moktamd wants to merge 2 commits intomedusajs:developfrom
moktamd:fix/product-list-null-sales-channel
Open

Fix product list crash with orphaned sales channel references#14961
moktamd wants to merge 2 commits intomedusajs:developfrom
moktamd:fix/product-list-null-sales-channel

Conversation

@moktamd
Copy link
Copy Markdown

@moktamd moktamd commented Mar 27, 2026

Fixes #14945

Summary

What — Filters out null/orphaned sales channel entries in the product list table and product detail views.

Why — When a sales channel is deleted without cleaning up the product-to-sales-channel join table, the API returns null entries in product.sales_channels. The dashboard crashes with TypeError: Cannot read properties of null (reading 'name') when rendering these entries.

How — Replaced unguarded .map() calls with a type-safe filter predicate that narrows (SalesChannelDTO | null)[] to SalesChannelDTO[] before accessing .name or .id. Applied in both SalesChannelsCell (product list table) and ProductSalesChannelSection (product detail page).

Testing — To reproduce:

  1. Create a product and assign it to a sales channel
  2. Delete the sales channel directly from the database (or via API) without removing the join-table entry
  3. Navigate to the product list — the page crashes
  4. With this fix, the product list renders normally, skipping the orphaned channel references. Tooltip counts and "available in X of Y" text reflect only valid channels.

Checklist

Filter out null entries from sales_channels arrays before rendering.
When a sales channel is deleted without cleaning up the join table,
the API returns null entries that crash the Admin UI with TypeError.
@moktamd moktamd requested a review from a team as a code owner March 27, 2026 14:39
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 27, 2026

🦋 Changeset detected

Latest commit: cd07c4a

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

This PR includes changesets to release 76 packages
Name Type
@medusajs/dashboard Patch
@medusajs/admin-bundler Patch
@medusajs/medusa Patch
@medusajs/test-utils Patch
@medusajs/medusa-oas-cli Patch
integration-tests-http 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/payment Patch
@medusajs/pricing Patch
@medusajs/product Patch
@medusajs/promotion Patch
@medusajs/rbac Patch
@medusajs/region Patch
@medusajs/sales-channel 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/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/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/core-flows Patch
@medusajs/framework Patch
@medusajs/js-sdk Patch
@medusajs/modules-sdk Patch
@medusajs/orchestration Patch
@medusajs/types Patch
@medusajs/utils Patch
@medusajs/workflows-sdk Patch
@medusajs/cli Patch
@medusajs/deps Patch
@medusajs/telemetry Patch
@medusajs/admin-sdk Patch
@medusajs/admin-shared Patch
@medusajs/admin-vite-plugin Patch
@medusajs/icons Patch
@medusajs/toolbox Patch
@medusajs/ui-preset Patch
create-medusa-app Patch
medusa-dev-cli 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

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 27, 2026

@moktamd is attempting to deploy a commit to the medusajs Team on Vercel.

A member of the Team first needs to authorize it.

@medusa-os-bot
Copy link
Copy Markdown

medusa-os-bot bot commented Apr 9, 2026

Thank you for your contribution!

After reviewing this PR, we need a few things addressed before we can move forward:

Required changes:

  • Add a changeset — run yarn changeset and select @medusajs/dashboard as a patch. The message must follow the format: fix(@medusajs/dashboard): short description
  • Fill in the PR description using our pull request template. The Testing section is missing — please describe how the reviewer can reproduce the crash and verify the fix (e.g., steps to create an orphaned sales channel reference and confirm the product list no longer crashes).

Notes:

  • filter(Boolean) is not a type-safe predicate in TypeScript — it won't narrow (SalesChannelDTO | null)[] to SalesChannelDTO[]. If you're adding null-filtering, consider a type guard instead:
.filter((sc): sc is SalesChannelDTO => sc !== null && sc !== undefined)

This ensures downstream .name accesses are type-safe after filtering.

  • The fix correctly addresses the UI crash, but the root cause is that the API returns null elements in product.sales_channels for orphaned join-table rows. It may be worth a follow-up issue on the backend side.

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.

Admin UI: Product list crashes with TypeError when product has orphaned sales channel reference

1 participant