vendure
v3.8.2Open-source headless commerce platform built with TypeScript, NestJS, React, and GraphQL
- Maintenance
- ActiveBased on the last push: commit history is not collected yet
- License
- OtherUnknown
- Security
- 30 advisories8 critical, 10 high, 8 medium, 4 low
- Supported versions
- No scheduleendoflife.date does not track this project
8.6k stars · 1.6k forks · 237 open issues · last release 3 days ago · data checked 5 hours ago
Breaking changes
What to check before upgrading, taken from the notes of the last 30 releases.
- v3.8.0Oct 12, 2026
Breaking Changes
v3.8 is a minor release, but a few changes need your attention. Each is covered in the Migration Guide below.
- Database migration required. The schema changes include a new unique constraint on every translation table.
- Order line promotion data migration. If you have partially cancelled order lines from before 3.8, you must run
rescaleOrderLinePromotionAdjustmentsin the same deployment as the upgrade. - NestJS 12,
@nestjs/graphql14 and Apollo Server 5. - Align any direct dependencies with these versions.
- GraphQL Playground is replaced by GraphiQL.
adminApiDebugandshopApiDebughave no effect.- Admin API sessions are bound to the Admin API (GHSA-5fpx-9m35-w745). Every administrator has to log in again once after the upgrade.
- Checkout recalculates the order on
ArrangingPaymentand refuses the transition if the selected shipping method is no longer eligible. ctx.session.tokenisstring | undefined, and is alwaysundefinedon job queue workers (GHSA-32jm-mf7r-7qw5 hardening).- The Dashboard sends only changed fields when updating Products, ProductVariants and Collections.
Migration Guide
This guide covers what you need to do when upgrading an existing Vendure project from v3.7 to v3.8. Update all
@vendure/*packages to the same version as described in Updating Vendure, then work through the checklist.Checklist
Every project:
- [ ] Back up your database, then generate and run a [database migration](#1-database-migration).
- [ ] Before upgrading, check whether you need the [order line promotion data migration](#2-order-line-promotion-data-migration). If you do, it must run in the same deployment as the upgrade. It cannot be added later.
- [ ] Update any of your own dependencies on
@nestjs/*or@apollo/serverto [NestJS 12 and Apollo Server 5](#3-nestjs-12-and-apollo-server-5). - [ ] Tell your administrators they will need to [log in again once](#4-admin-api-sessions-are-bound-to-the-admin-api) after the upgrade.
Check these if they apply to you:
- [ ] Storefronts: handle the new [checkout refusal for ineligible shipping methods](#5-checkout-recalculates-prices-and-re-checks-shipping-eligibility).
- [ ] Plugins that read
ctx.session.tokenin job queue workers: see [RequestContext.session.tokenis optional](#6-requestcontextsessiontoken-is-optional). - [ ] Custom resolvers or event handlers for Product, ProductVariant or Collection updates: see [partial updates from the Dashboard](#7-the-dashboard-sends-only-changed-fields-for-some-updates).
- v3.7.0Jul 1, 2026
Breaking Changes
v3.7 is a minor release, but a few changes need your attention.
- Coupon codes are now compared case-insensitively (#4419), bringing Vendure in line with other commerce platforms. This only affects you if you've used different-case versions of the same code for *distinct* promotions — those will now collide.
- The default superadmin password is refused in production (#4718). If your production environment still uses the default superadmin password, Vendure will not start. Change it before upgrading.
- External authentication now requires a verified email to link to an existing account. As part of the fix for the account-takeover advisory (GHSA-6j36-r6pr-59x4), an external login is only linked to a pre-existing account when the external email is verified. If you have a custom
AuthenticationStrategy, it must setverified: trueon the returned user data for provider-verified emails, otherwise the link is refused. Creating new accounts is unchanged. - Email plugin dependency upgrades:
mjml4 → 5 andnodemailer6 → 9. If you use MJML email templates or a custom nodemailer transport configuration, review these major upgrades for behavioural changes. @nestjs/terminusis no longer a transitive dependency - since we deprecated health checks for external components in v3.6, we were able to eliminate this dependency from Vendure core. However, if you have your own health check code which depends on this package, you'll need to add@nestjs/terminusas a direct dependency of your project rather than relying on it being present due to Vendure Core.
Migration Guide
See the v3.7 Migration Guide for detailed, example-driven steps on each of the changes above.
- v3.5.6Mar 30, 2026
PathAdaptergets newsourceRootoption ⚠️ BREAKING CHANGE IN EDGE CASES — where monorepos using a custompathAdapter.getCompiledConfigPathcannot build the dashboard because the output directory structure is flattened: If you use a custompathAdapter, setsourceRootto your workspace root to restore correct nesting:
- v3.5.0Oct 22, 2025
Breaking Changes: SentryPlugin
We have updated the underlying library used in our
@vendure/sentry-pluginpackage in order to bring it into line with the latest Sentry version and the recommended way of instrumenting NestJS-based apps.First you can simplify the options passed to the SentryPlugin:
// before SentryPlugin.init({ dsn: process.env.SENTRY_NODE_DSN, environment: process.env.SENTRY_ENV, tracesSampleRate: 0.1, }), // after SentryPlugin.init(),With the new version, the Sentry DSN is provided as an environment variable, and you'll need to alter the way you run your server to pre-load the plugin's instrumentation file. See the SentryPlugin docs for a complete guide.
Note: If you are unable to update right away, it's perfectly safe to keep using v3.4.x of the SentryPlugin while you plan in the upgrade.
- v3.4.0Aug 1, 2025
- 4. Read over the BREAKING CHANGE section below to see if there are any changes you need to know about.
BREAKING CHANGE
- If you are using the
MolliePlugin, you should install @mollie/api-client@4.3.3 as the plugin has been updated to use the latest Mollie features. - Indexes have been added on the columns
orderPlacedAtin the Order table, andcreatedAtin the JobItem table (for those using the DefaultJobQueuePlugin). This will require a non-destructive DB migration be performed to add these indexes to your schema. - With the introduction of the new SettingsStore feature, a non-destructive database migration will be required to set up the new table that will store the settings data.
Release history
All releases on GitHubVendure v3.8.2 is a patch release containing a batch of core, dashboard, CLI, @vendure/create and plugin fixes, including a fix for Dashboard extension pages which broke after a redeploy.
If you use RedisCachePlugin, cancel Orders from the ArrangingAdditionalPayment state, serve resized SVG assets, or script vendure auth status or @vendure/create, read Behaviour Changes.
Core
- Recalculating an unchanged Order gives the same totals every time when an item-level Promotion depends on an order total condition such as
minimum_order_amount(#5663, closes #5605). Before, the result could alternate between two values. updatePromotionchecks that each action has its required condition, ascreatePromotiondoes (#5676, closes #5675). Before, an update could leavebuy_x_get_y_freewithout its condition, and order price calculation then threwCannot read properties of undefined (reading 'freeItemsPerLine').- An Order in
ArrangingAdditionalPaymentcan only move toCancelledonce all of its lines are cancelled, as from every other state (#5672, closes #5671). Before, the check was skipped and allocated stock was not released. - The default search index includes every variant passed to
updateVariantsByIdandupdateVariants, not only the first 50 (#5674, closes #5673). This showed when a Collection gained more than 50 variants at once:search({ collectionId })returned 50 of them. - A Customer cannot change their email address to one which belongs to another Customer, including a guest Customer with no User (#5680, relates to #5640). The request returns
EmailAddressConflictError. Before, two Customers could end up with the same address. authenticatereturnsInvalidCredentialsErrorfor an empty input or a strategy withnulldata, instead of an internal error with no error code (#5622, closes #5621).createAssetswithtranslationsand no custom fields returns the translated Asset (#5713). Before, selectingnamefailed with "Cannot return null for non-nullable field Asset.name".- Blocking event handlers:
- A circular dependency between three or more handlers is reported with a
Circular dependency detectederror which names the handlers, instead ofRangeError: Maximum call stack size exceeded(#5632, closes #5630). A handler whose registration was rejected no longer stays registered. - Two handlers which declare the same constraint from both sides (A is
afterB, and B isbeforeA) are ordered instead of throwing aRangeError(#5665, closes #5664). RedisCacheStrategyremoves expired entries from its tag sets and gives each tag set an expiry, so tag sets no longer grow without limit (#5683, closes #5682). The session cache tag gained one member per session.invalidateTagsnow works in batches of 1000 and throws on a command error instead of ignoring it.- The polling job queue waits for a job which is being claimed before it stops (#5565, relates to #4949). Before, the application could close while the job was already marked
RUNNING, and nothing settled it afterwards. - A migration no longer de-duplicates translations in a table which the same migration creates, and logs de-duplication only when it removes rows (#5702). New projects no longer log "The … table does not exist. Skipping de-duplication." for every translation table.
Dashboard
- Every build gives its JavaScript chunks new file names (#5772, closes #5564). Before, an extension chunk could keep its file name while the entry chunk it imports got a new one. Because
/assetsis cached as immutable, the browser then ran the old chunk, and extension pages showed "Not Found" or failed withCannot read properties of null (reading 'useContext')after a redeploy. - After logging out and signing in as another user, the Dashboard loads that user's settings (#5669). Before, the new user saw the previous user's settings, and their active Channel was saved into the new user's settings.
- Dashboard widgets keep the position given in
defaultSize.xanddefaultSize.ywhen the user has no saved layout and the position is free (#5658, closes #5616). The built-in widgets have new default positions. - Expanded child Collections reload in the new language when you switch the content language (#5706, closes #5704).
- Changing a line's quantity in Modify order and on the draft order page works when the OrderLine has a relation custom field (#5697, closes #5696). The field was sent by its output name, which the API rejects.
- The asset picker's select button, the upload toasts and the move Collections dialog use proper plurals in every locale (#5590, relates to #5482).
- In
useExperimentalBundlemode, styles match source mode (#5709). Before, selects could render too narrow and some@vendure-io/uiclasses, such as the breadcrumb separator, were missing.
CLI and @vendure/create
vendure console linkhas a new--console-projectoption which selects the Console Project without the picker (#5685). With--non-interactiveit creates the Project Link from the login stored byvendure auth login.vendure auth loginandvendure auth statuscheck that the stored login can still be renewed (#5689). Before, a login which could no longer be renewed was reported as valid.vendure console linksays when the stored login has expired or was revoked, instead of "No CLI login … is stored on this machine" (#5710).- The unknown-command hint names an inactive CLI plugin only when that plugin declares the command, and treats a plugin enabled for the project as active (#5692).
@vendure/createno longer hangs when the Docker daemon does not answer (#5693). The daemon check gives up after 10 seconds anddocker compose upafter 5 minutes.@vendure/createexits with code 1 when it cannot copy the email templates (#5694). Before, it stopped with exit code 0.
Plugins
- Asset Server Plugin: a resized
.svgasset with noformatparameter is served asimage/png, which is what the response body contains (#5255). Before, it was labelledimage/svg+xml, and since 3.7.3 the browser downloaded it instead of displaying it. - GraphiQL Plugin: the GraphiQL page sends requests to the server which served it (#5686). Before, a server with
apiOptions.hostnameset, for example0.0.0.0in Docker, sent the page an address the browser could not reach. A customroutenow works too. - Job Queue Plugin:
BullMQJobQueueStrategywaits for its Redis connection to be ready before it subscribes to job cancellations (#5631, closes #5627). Before, the subscription could be lost during startup, and cancelling a running job did nothing. - MCP Plugin:
adjust_stocklocks the stock levels it reads, so concurrent calls no longer overwrite each other (#5653, closes #5652).upload_assetpublishes anAssetEventof typecreated, as thecreateAssetsmutation does (#5662, closes #5661).- An OAuth bearer token resolves on PostgreSQL with
UuidIdStrategy(#5705, closes #5701). Before, it failed withoperator does not exist: uuid = character varying. Sessions created for MCP clients also record the caller's API type. - The Dashboard navigation titles of the plugin are translated, and no longer log "Uncompiled message detected!" (#5660, closes #5641).
- MCP SDK:
idSchemaconverts an id sent as a string of digits, such as"9", to a number when the id strategy is auto-increment (#5647, closes #5626). Before,adjust_stock,update_variant,update_productandupdate_customerfailed with a database error.
Behaviour Changes
No APIs are removed or renamed.
Redis cache tags. RedisCacheStrategy stores tags in sorted sets under a new key name, :ztag:. The old :tag: sets get no new members, and invalidateTags still empties them. During a rolling deploy, an invalidation on an instance still on the old version does not clear entries tagged by upgraded instances. Those entries expire with their TTL. Tagged writes use EVAL, so a Redis ACL user needs the @scripting permission. The documented minimum is Redis 3.2, or a compatible server such as Valkey.
Cancelling from ArrangingAdditionalPayment. The transition to Cancelled now fails unless every line of the Order is cancelled.
Updating a Promotion. updatePromotion returns the same error as createPromotion when an action's required condition is missing. The check runs only when the update sends conditions or actions, so a Promotion already saved without its condition can still be disabled or renamed.
Resized SVG assets. These are cached under a .png file name and served as image/png.
GraphiQL Plugin. The page no longer uses apiOptions.hostname to build its request URLs.
Dashboard build output. JavaScript file names in the build output change with every build, even when the source is unchanged. Set disablePlugins.chunkHash in the Vite plugin options to turn this off.
CLI exit codes and output. vendure auth status exits with 1 when the stored login cannot be renewed, and its --json output has two new fields, renewable and renewalError. @vendure/create exits with 1 when the email templates cannot be copied or the Docker daemon does not answer.
Migration
No database migrations are required. Upgrade all @vendure/* packages together to 3.8.2.
What's Changed
- fix(mcp-sdk): convert numeric id strings of tool inputs to numbers by @Ryrahul in https://github.com/vendurehq/vendure/pull/5647
- fix(core): clear item promotion adjustments before testing conditions by @AyeshaWaseemAhmad in https://github.com/vendurehq/vendure/pull/5663
- fix(job-queue-plugin): subscribe to job cancellations once the connection is ready by @AyeshaWaseemAhmad in https://github.com/vendurehq/vendure/pull/5631
- fix(dashboard): initialize user settings from the next session after logout by @AyeshaWaseemAhmad in https://github.com/vendurehq/vendure/pull/5669
- fix(mcp-plugin): lock the stock levels which adjust_stock reads by @Ryrahul in https://github.com/vendurehq/vendure/pull/5653
- ci: use Bun 1.4.4 in all workflows by @dlhck in https://github.com/vendurehq/vendure/pull/5681
- chore: add build and threat model for Anthropic OSS Scanner by @michaelbromley in https://github.com/vendurehq/vendure/pull/5677