Skip to content

fix(core): Handle empty sortedAssets in updateEntityAssets - #4397

Merged
michaelbromley merged 2 commits into
vendurehq:masterfrom
colinpieper:fix/empty-sorted-assets-crash
Feb 26, 2026
Merged

fix(core): Handle empty sortedAssets in updateEntityAssets#4397
michaelbromley merged 2 commits into
vendurehq:masterfrom
colinpieper:fix/empty-sorted-assets-crash

Conversation

@colinpieper

@colinpieper colinpieper commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

Description

AssetService.updateEntityAssets() crashes when assetIds contains IDs that don't exist in the current channel. After findByIdsInChannel filters them out, sortedAssets becomes empty and createOrderableAssets crashes accessing [0] on the empty array:

TypeError: Cannot read properties of undefined (reading 'constructor')                                                                                                                                                                            
  at createOrderableAssets (asset.service.ts)                                                                                                                                                                                                     

The guard at line 273 only checks the input assetIds array, not the filtered result. This adds an empty check on sortedAssets before calling createOrderableAssets, matching the behavior of the else if branch which already handles explicitly empty assetIds.

Fixes #4398

Breaking changes

No

Checklist

📌 Always:

  • I have set a clear title
  • My PR is small and contains a single feature
  • I have checked my own PR

👍 Most of the time:

  • I have added or updated test cases
  • I have updated the README if needed

When assetIds contains IDs not present in the current channel,
findByIdsInChannel filters them out leaving sortedAssets empty.
createOrderableAssets then crashes accessing index [0] on the
empty array. Guard against this by checking sortedAssets.length.
@vercel

vercel Bot commented Feb 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vendure-storybook Ready Ready Preview, Comment Feb 23, 2026 3:07pm

Request Review

@coderabbitai

coderabbitai Bot commented Feb 23, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This pull request adds a test case and modifies asset handling logic. The test file includes a new test case verifying that updating a product with asset IDs not present in the current channel clears the product's assets without crashing. The asset service is updated to explicitly set entity.assets to an empty array when no matching assets are found during an update, instead of attempting to create orderable assets from an empty list. This ensures consistent behavior when provided asset IDs do not correspond to existing Asset records.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main bug fix: handling empty sortedAssets in the updateEntityAssets method.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description comprehensively covers the issue, fix, and includes relevant checklist items completed, though README update was appropriately skipped.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/core/src/service/services/asset.service.ts (1)

279-283: Fix is correct — minor inconsistency with the else if branch worth aligning.

The guard correctly prevents calling createOrderableAssets on an empty array, fixing the TypeError. However, there's now a behavioural asymmetry in updateEntityAssets:

Scenario DB state entity.assets in memory
assetIds non-empty, all filtered out (new path) orderable assets removed ✅ set to []
assetIds is [] (existing else if) orderable assets removed ✅ not updated — stale value remains

Any caller that passes assetIds: [] and uses the returned entity without reloading will see stale assets in memory. Consider aligning the else if branch:

♻️ Suggested fix for consistency
     } else if (assetIds && assetIds.length === 0) {
         await this.removeExistingOrderableAssets(ctx, entity);
+        entity.assets = [];
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/service/services/asset.service.ts` around lines 279 - 283,
In updateEntityAssets, the branch handling the case where assetIds is an empty
array leaves entity.assets unchanged causing stale in-memory assets; align it
with the other branch by setting entity.assets = [] when you removed orderable
assets (the same place you use createOrderableAssets/sortedAssets logic) so
callers receive the updated empty assets list; locate the updateEntityAssets
method and after the DB removal path for assetIds === [] explicitly assign
entity.assets = [].
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/e2e/asset-channel.e2e-spec.ts`:
- Around line 291-305: The new test "Updating product with asset IDs not in
channel does not crash" causes global deletion by removeExistingOrderableAssets
(called from updateEntityAssets), which clears all orderable assets for product
T_2 and makes the subsequent "Channel2 does not have asset A" test vacuously
pass; either move this new test to run after the channel-isolation test, or add
a follow-up assertion using adminClient in the default channel to confirm T_2
still has asset T_3 (verifying deletion was channel-scoped), and if global
deletion is intended update the test comment to state that explicitly; reference
removeExistingOrderableAssets, updateEntityAssets, the test updating product
with id 'T_2' and asset 'T_3', and the "Channel2 does not have asset A" test
when applying the change.

---

Nitpick comments:
In `@packages/core/src/service/services/asset.service.ts`:
- Around line 279-283: In updateEntityAssets, the branch handling the case where
assetIds is an empty array leaves entity.assets unchanged causing stale
in-memory assets; align it with the other branch by setting entity.assets = []
when you removed orderable assets (the same place you use
createOrderableAssets/sortedAssets logic) so callers receive the updated empty
assets list; locate the updateEntityAssets method and after the DB removal path
for assetIds === [] explicitly assign entity.assets = [].

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8e0011 and 73611b6.

📒 Files selected for processing (2)
  • packages/core/e2e/asset-channel.e2e-spec.ts
  • packages/core/src/service/services/asset.service.ts

Comment thread packages/core/e2e/asset-channel.e2e-spec.ts
@michaelbromley
michaelbromley merged commit 6c81359 into vendurehq:master Feb 26, 2026
17 checks passed
@michaelbromley

Copy link
Copy Markdown
Member

Thank you!

@vendure-ci-automation-bot vendure-ci-automation-bot Bot locked and limited conversation to collaborators Feb 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AssetService.updateEntityAssets() crashes when assetIds are not in the current channel

2 participants