Back to publishing & release Automate semantic versioning Publish to the npm registry Harden the supply chain

Fixing Changesets Not Detecting a Version Bump

You merged a change but the Changesets release PR proposes no version bump, so the fix never ships. This page shows why Changesets sees nothing to release and how to make bumps deterministic.

Exact symptoms and error messages

Exact symptoms and error messages Exact symptoms and error messages in production JavaScript package workflows. Exact symptoms and error messages Exact symptoms and error messages in production JavaScript package workflows.
Exact symptoms and error messages — the core idea of this section at a glance.
$ pnpm changeset status
No changesets found. All packages up to date.
# but a fix was merged with no version change

Root cause analysis

Changesets derives version bumps from intent files in .changeset/, not from your commits. If no changeset file was added for the change, there is nothing to release — the tool has no signal that a package changed. This is the intent-driven half of Semantic Versioning and Release Automation; the alternative, commit-driven approach is covered in Configuring Conventional Commits and semantic-release.

Intent to release A changeset intent file drives the version and publish. add changeset .changeset/*.md version PR computed bump merge → publish release ships
Changesets releases from intent files, so no changeset means no release.

Changesets is intent-driven: it releases from the .changeset/*.md files a contributor adds, not from the commits themselves. If no changeset was added for a change, the tool correctly sees nothing to release — from its perspective, the change declared no user-facing impact. The gap is not a bug in Changesets; it is a missing intent file, which is easy to forget because the code change on its own looks complete.

This is the deliberate trade-off of the intent-driven model versus the commit-driven one. Commit-driven tools like semantic-release infer the bump from commit messages, so nothing is forgotten but the message format becomes load-bearing. Changesets asks for an explicit statement of intent, which is more work per change but produces a human-written changelog entry and a clear record of why each version moved. Neither is wrong; the failure here is simply that the intent-driven tool was used without supplying the intent.

Changesets is intent-driven: it computes releases from the intent files a contributor adds under .changeset/, not from the commits themselves. When no changeset file was added for a change, there is nothing for the tool to release — from its perspective the change declared no user-facing impact, so changeset version produces no bump and changeset status reports nothing to release. The gap is not a bug but a missing intent file, which is easy to overlook because the code change on its own looks complete.

This is the deliberate trade-off of the intent-driven model versus the commit-driven one. Commit-driven tools like semantic-release infer the bump from commit messages, so nothing is forgotten but the message format becomes load-bearing; Changesets asks for an explicit statement of intent, which produces curated changelogs at the cost that the intent can be forgotten. The fix for a missing bump is therefore to add the changeset — and, structurally, to enforce that a changeset accompanies any change to a publishable package so the intent is never omitted.

Resolution and configuration patch

Add a changeset for every user-facing change and enforce it in CI:

Resolution and configuration patch Add a changeset for every user-facing change and enforce it in CI: Resolution and configuration patch Add a changeset for every user-facing change and enforce it in CI:
Resolution and configuration patch — the core idea of this section at a glance.
# create an intent file describing the bump
pnpm changeset
# CI: fail a PR that changes packages but adds no changeset
- run: pnpm changeset status --since=origin/main

The status check turns a missing changeset into a red build instead of a silent no-op release.

Add a changeset for the change, and enforce the requirement in CI so it cannot be forgotten:

# Author an intent file describing the bump
pnpm changeset
# CI: fail a PR that changes a publishable package with no changeset
- run: pnpm changeset status --since=origin/main

The changeset status --since check exits non-zero when a package changed without an accompanying changeset, turning a silent no-op release into a red build. For a deliberately non-releasing change — a refactor or a docs edit — add an empty changeset to record that intent explicitly rather than leaving it ambiguous.

CLI validation and debug commands

CLI validation and debug commands CLI validation and debug commands in production JavaScript package workflows. CLI validation and debug commands CLI validation and debug commands in production JavaScript package workflows.
CLI validation and debug commands — the core idea of this section at a glance.
# Show what will be released
pnpm changeset status --verbose
# Confirm intent files exist for the change
ls .changeset/*.md

Prevention and CI guardrails

  • Require a changeset on any PR that modifies a publishable package.
  • Run changeset status --since=<base> in CI to block missing intents.
  • Educate contributors that commits alone do not trigger a release.
  • Use empty changesets deliberately when a change is intentionally non-releasing.
Prevention and CI guardrails Prevention and CI guardrails in production JavaScript package workflows. Prevention and CI guardrails Prevention and CI guardrails in production JavaScript package workflows.
Prevention and CI guardrails — the core idea of this section at a glance.
  • Require a changeset on any pull request that modifies a publishable package.
  • Run changeset status --since=<base> in CI as a required check so missing intents fail the build.
  • Use an empty changeset to record a deliberately non-releasing change explicitly.
  • Educate contributors that commits alone do not trigger a Changesets release — the intent file does.

Enforcing a changeset in CI

The reliable fix is to make a missing changeset fail the pull request, so the intent file is never forgotten. Changesets ships a status command that can compare against a base and exit non-zero when a publishable package changed without an accompanying changeset.

Changeset CI gate A status check fails a PR missing its changeset. changeset status compare to base missing intent red build contributor adds release recorded
A required status check makes the intent-driven model self-enforcing.
- run: pnpm changeset status --since=origin/main

As a required check, this turns a silent no-op release into a red build on the PR that introduced the gap — the contributor is prompted to run pnpm changeset and describe the bump before merge. Deliberately non-releasing changes (a refactor, a docs edit) are handled by adding an empty changeset, which explicitly records 'no release needed' rather than leaving the intent ambiguous. The check makes the intent-driven model self-enforcing instead of relying on everyone remembering the extra step.

Intent-driven versus commit-driven automation

Choosing between Changesets and semantic-release is really choosing where the release intent lives. Changesets puts it in explicit intent files a contributor writes, which produces curated changelogs and handles monorepos with independently-versioned packages naturally. semantic-release infers it from conventional commit messages, which never forgets a bump but ties correctness to commit discipline and is happiest with single-package repos.

Intent vs commit Changesets against semantic-release. Model Intent lives in Best for Changesets intent files monorepos + changelogs semantic-release commit messages single-package repos
Explicit intent files versus inferred bumps from commit messages.

For a monorepo publishing several packages with human-readable changelogs, Changesets' explicit model usually wins despite the extra per-change step — and the CI status check removes the 'forgot the changeset' failure mode. For a single package where every commit already follows a convention, semantic-release's zero-extra-step automation is hard to beat. The conventional-commits setup covers the commit-driven alternative in full; the key is to pick one model and enforce it, rather than half-adopting both.

How Changesets computes versions from intent files

Understanding what a changeset file contains clarifies why a missing one produces no release. Each changeset is a small markdown file declaring which packages changed and at what bump level — major, minor, or patch — plus a human-readable description of the change. When changeset version runs, it reads all accumulated changesets, computes each package's next version from the highest bump that applies to it, walks the dependency graph to bump packages that must move because a dependency did, updates the manifests and changelogs, and deletes the consumed changeset files. No changeset means no input to that computation, so no version moves.

Intent to release Changesets read, versions computed, changelogs written. add changesets .changeset/*.md changeset version compute per package update + changelog consume intents
Changesets computes each package's version from the intent files that name it.

This model is what makes Changesets well-suited to monorepos with independently-versioned packages. Because each changeset names specific packages and bump levels, the tool can compute a different next version for each package based on the changes that actually touched it, so a consumer of one package is not forced to upgrade because an unrelated sibling shipped a major. The intent files also become the changelog, written for a human deciding whether to upgrade rather than a developer reading commit history. The cost of this precision and clarity is exactly the failure mode of a forgotten changeset — which is why enforcing the changeset requirement in CI is the natural complement to adopting the model.

Choosing intent-driven or commit-driven automation

A missing-bump problem is often a prompt to reconsider which release-automation model fits the team. Changesets' intent-driven approach asks for an explicit changeset per change, which produces curated changelogs and handles independently-versioned monorepo packages naturally, at the cost that the intent can be forgotten without a CI gate. semantic-release's commit-driven approach infers the bump from conventional commit messages, so nothing is forgotten, but correctness depends on commit discipline and it is happiest with single-package repositories.

Automation models Changesets versus semantic-release. Model Intent from Best for Changesets intent files monorepos + changelogs semantic-release commit messages single packages
Intent files curate changelogs; commit inference never forgets a bump.

The practical dividing line is repository shape and changelog needs. A monorepo publishing several packages with changelogs a human will actually read is usually better served by Changesets, with a changeset status check enforcing the intent. A single package where every commit already follows a convention is well served by semantic-release's zero-extra-step automation. Neither is wrong; the missing-bump symptom simply means that whichever model you have chosen is not being enforced. Picking one deliberately and enforcing it in CI — a status check for Changesets, a commit linter for semantic-release — is what makes the version always derive from the changes rather than depending on someone remembering a step.

Handling internal dependency bumps in a monorepo

A subtlety of Changesets in a monorepo is that a change to one package can require bumping the packages that depend on it, and understanding how this works prevents a different kind of missing-bump surprise. When you add a changeset for @acme/core, Changesets can automatically bump the dependents that reference it — a patch bump by default — so that a consumer of @acme/ui receives a version that pulls in the fixed @acme/core. The updateInternalDependencies setting controls whether this happens on patch or only on minor-and-above changes.

Internal dependent bumps A changed package bumps the dependents that reference it. changeset for core the changed package bump dependents per threshold consumers get the fix propagated
Configure the internal-dependency threshold so a change propagates to its consumers.

If you find that a dependent package did not get released after a dependency changed, the cause is usually this configuration: the internal-dependency update threshold was set higher than the bump you made. Aligning it with how tightly your packages couple — patch-level updates for tightly-linked packages, minor-and-above for more independent ones — ensures that a change propagates to the consumers that need it. This is the monorepo-specific complement to the basic missing-bump problem: not only must each changed package have a changeset, but the tool must be configured to bump the dependents whose behavior the change affects.

Frequently Asked Questions

Why doesn't merging a fix trigger a release?

Changesets releases from intent files, not commits. Without a .changeset/*.md file describing the bump, the tool correctly sees nothing to release. Add a changeset with the change.

How do I enforce changesets in CI?

Run changeset status --since=origin/main as a required check; it fails when a PR touches a package but adds no changeset, so missing intents are caught before merge.

Why doesn't merging a fix trigger a Changesets release?

Because Changesets releases from intent files, not commits. Without a .changeset/*.md describing the bump, the tool correctly sees nothing to release. Add a changeset with pnpm changeset, or enforce one in CI.

How do I enforce changesets so none are forgotten?

Run changeset status --since=origin/main as a required check. It fails a PR that changes a publishable package without a changeset, prompting the contributor to add one before merge.

Changesets or semantic-release — how do I choose?

Changesets uses explicit intent files, ideal for monorepos with curated changelogs; semantic-release infers bumps from conventional commits, ideal for single packages with commit discipline. Pick one model and enforce it rather than half-adopting both.

Why doesn't merging a change trigger a Changesets release?

Because Changesets releases from intent files under .changeset/, not from commits. Without a changeset describing the bump, the tool correctly sees nothing to release. Add one with pnpm changeset, and enforce a changeset status check in CI so the intent is never forgotten.

How do I record a change that should not trigger a release?

Add an empty changeset, which explicitly declares no release is needed rather than leaving the intent ambiguous. This passes a changeset status gate while correctly producing no version bump for a refactor or docs-only change.

Should I use Changesets or semantic-release?

Changesets (intent files) suits monorepos with curated changelogs; semantic-release (conventional commits) suits single packages with commit discipline. A recurring missing-bump problem usually means the chosen model is not enforced — add a changeset status check or a commit linter.

Why didn't a dependent package get released when its dependency changed?

Changesets bumps internal dependents based on the updateInternalDependencies threshold. If it is set to minor-and-above and you made a patch change, dependents are not bumped. Lower the threshold for tightly-coupled packages so a change propagates to the consumers that need it.

Can I add a changeset after merging the change?

Yes — a changeset is just a file, so you can add one in a follow-up PR to release a change that merged without it. But the reliable practice is a changeset status CI check that blocks the original PR, so the intent is captured with the change rather than remembered later.

Related

Semantic Versioning and Release Automation