Skip to content

Default version.preset ("conventional") can't be loaded; a bad preset crashes release/standing-pr with an unhandled rejection and no envelope #652

Closed

Description

@goosewobbler

Problem

  1. The default preset doesn't exist. version.preset defaults to "conventional" (packages/config/src/schema.ts:92, packages/version/src/types.ts:220,231). The preset loader prefixes it to conventional-changelog-conventional, which isn't on npm (404). So every config without an explicit version.preset — including the one releasekit init writes, and repos with no config file — fails whenever the bump is inferred from commits (only --bump escapes it). The repo's own config pins angular, and every integration/e2e test pins angular or conventionalcommits, so nothing exercises the default.
  2. An unloadable preset crashes the CLI on tagged repos. Bumper.loadPreset() (packages/version/src/core/versionCalculator.ts:386) starts the preset import() without a handler; the following await refExists(latestTag, …) (line 393) yields, the import rejects, and Node's default --unhandled-rejections=throw kills the process before the surrounding try/catch runs. release --json [--output] and standing-pr update --json --output exit 1 with no envelope (stdout empty, no --output file) — breaking the feat(cli): uniform JSON envelope with structured errors and changed reporting #608 envelope contract. On untagged repos the && short-circuits, the error is caught, and a GENERAL_ERROR envelope is written — still exit 1, not a config error.
  3. The docs disagree on the default: "conventional" (docs/configuration.md, docs/migration.md, packages/config/README.md), "conventionalcommits" (packages/version/README.md, docs/troubleshooting.md), plus dead fallbacks 'conventional-commits' (versionEngine.ts:89-91) and 'angular' (versionCalculator.ts:146).

Regression note: the crash (as opposed to a clean failure) dates from 4431910 (#437, v0.33.0), which made refExists async; the default preset itself was never loadable.

Reproduction (built CLI, Node 22)

git init -q demo && cd demo && git config user.email t@e && git config user.name t
echo '{"name":"demo-pkg","version":"1.0.0"}' > package.json
echo '{"version":{}}' > releasekit.config.json      # or no config, "conventional", or "nonsense"
git add -A && git commit -qm "chore: init" && git tag v1.0.0
echo x > a.txt && git add -A && git commit -qm "feat: add a"
releasekit release --json --dry-run --output out.json; echo "exit=$?"; ls out.json

Exit 1, empty stdout, no out.json; stderr ends in an uncaught Unable to load the "conventional" preset (ERR_MODULE_NOT_FOUND: conventional-changelog-conventional) with a Node crash footer. angular / conventionalcommits work. conventional-commits works in flat npm/pnpm installs (hoisted alias from @releasekit/version) but not from the bundled packages/release/dist CLI the GitHub Action runs, because the preset loader is bundled into release's dist and import() resolves from there (NODE_PATH doesn't apply to ESM).

Impact

  • New users following getting-started (releasekit init, then a release) fail on every commit-inferred release; after their first tag it's a raw crash with a bundled-code stack.
  • In CI, release / standing-pr update exit 1 with no envelope, so the standing PR is never created or updated; the Action's summary says only "Release Failed", with the cause buried in the log.
  • A typo'd preset fails the same way, and even the handled path reports GENERAL_ERROR (exit 1) rather than CONFIG_ERROR (exit 2).

Proposed fix

  1. Loadable default: default to conventionalcommits; normalise conventional and conventional-commits to it (nobody's behaviour changes — conventional never loaded); regenerate the schema; drop the dead fallbacks.
  2. Layout-independent loading: pass a loader to Bumper.loadPreset(preset, loader) that maps the supported names to static imports of conventional-changelog-angular / conventional-changelog-conventionalcommits (resolve any others via createRequire(projectDir) if custom presets are to be supported), then drop the conventional-changelog-conventional-commits alias dependency.
  3. Validate at config load: an unknown preset throws ConfigError listing the supported names → exit 2 and a CONFIG_ERROR envelope.
  4. Close the unhandled window: load the preset (awaited) inside the try before configuring the bumper — or at minimum do the refExists await before loadPreset — so nothing yields between starting the import and bump().
  5. Docs: one stated default and supported list across configuration.md, migration.md, troubleshooting.md, and the version/config READMEs.

Acceptance criteria

  • Tagged repo, no preset (or "conventional"): releasekit release --json --dry-run exits 0 with conventionalcommits rules — in npm, pnpm, and the GitHub Action (bundled release/dist) layouts.
  • "preset": "nonsense", tagged and untagged: release and standing-pr update exit 2 with a CONFIG_ERROR envelope (stdout and --output) listing supported presets; a one-line stderr message; no crash footer.
  • No unhandledRejection for any preset value under default Node settings.
  • Tests: no-preset on a tagged repo (integration/e2e); unknown-preset config validation; CONFIG_ERROR envelope written to --output; an alias resolving from the bundled release CLI.
  • Every doc names the same default.

Related: #544 (envelope contract), #616 (envelopes version/publish — coordinate the version path).

Activity

  1. added this to the 0.42.0 milestone on Oct 22, 2026
  2. added 2 commits that reference this issue on Oct 23, 2026
    9c82142
    db9be37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:highHigh priority issue or PRtype:bugSomething isn't working

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions