Minimal repros for aube compatibility issues found while testing existing npm and Bun projects.
npm-lock-add-reresolve(observed with aube1.38.1):aube installtreats a fresh npmpackage-lock.jsonas up to date, butaube addof a named spec re-resolves unrelated hoisted versions. The fixture pinsjest-config@29.7.0exactly. The lockfile was produced by npm11.17.0withnpm install --ignore-scripts --package-lock-only --no-audit --no-fund; npm12.0.2left that lock byte-identical. npm hoistscamelcase@5.3.1and nestscamelcase@6.3.0underjest-validate. Realnpm install is-number@7.0.0only promotes that already-transitive package.aube add is-number@7.0.0hoistscamelcaseto6.3.0. The same rewrite happens foraube add jest-config@29.7.0(already the exact pin) andaube install --fix-lockfile, with either isolated or hoistedAUBE_NODE_LINKER. Smaller trees (express,esbuild, a two-packagecamelcasepair) do not reproduce the hoist. Docs: https://aube.jdx.dev/package-manager/install, https://aube.jdx.dev/package-manager/lockfiles, https://aube.jdx.dev/package-manager/dependencies Related: #1155 expected anaddlock diff to contain only the new package; #938 is optional-native recording, not unrelated version hoists;npm-lock-missing-entryis a different--fix-lockfilemissing-path case. Upstream discussion: jdx/aube#1286
Confirmed aube design differences from pnpm (or other managers). Kept for migration notes; the repro still exits non-zero while the difference holds.
pnpm-min-release-age(observed with aube1.37.0, retested on1.37.0): aube documents pnpm 11's defaultminimumReleaseAge: 1440(24h), but under the defaultminimumReleaseAgeStrict: falseit still installs an exact pin whose only matching version was published "now", and it does not re-verify published age for existing lockfile entries. Native pnpm 11 rejects the same tree withERR_PNPM_NO_MATURE_MATCHING_VERSIONon cold resolve andERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATIONwhen reinstalling from a lockfile that already pins the young version. SettingminimumReleaseAgeStrict: truemakes aube reject on resolve (ERR_AUBE_NO_MATURE_MATCHING_VERSION). Maintainer confirmed this is intentional: lockfile pins are authoritative, and the age gate applies when resolving a new version rather than revalidating existing lock entries; strict mode is the opt-in hard fail on fresh resolve. The associated fix PR was closed without merge. The repro uses a local mock registry that always reportspublishedAt=nowso the case is durable without a same-day public publish. Migration note: projects that relied on pnpm 11's default hard age gate should setminimumReleaseAgeStrict: true(and not expect lockfile re-verification). First seen installing@opencode-ai/sdk@0.0.0-beta-202608061351in a monorepo that relied on the pnpm 11 default age gate (no explicitminimumReleaseAgekey). Docs: https://aube.jdx.dev/security, https://aube.jdx.dev/settings/#setting-minimumreleaseage, https://pnpm.io/supply-chain-security Upstream discussion: jdx/aube#1240 Closed PR (not merged): jdx/aube#1241
-
hoisted-workspace-shared-dep-realpath(observed with aube1.37.0, fixed in aube1.38.1, retested on1.38.1): in a two-package workspace that pins the same version of a dependency in both packages,aube install --node-linker=hoistedused to materialize distinct real directories at each package'snode_modules/<dep>, so Node and bundlers loaded multiple module instances. The linker now plans one workspace-wide hoisted tree; with defaulthoistingLimits=none, compatible deps hoist to a single workspace-root placement. Package-localnode_modules/<dep>slots may be absent; the repro asserts identity withrequire.resolve(..., { paths })from each importer. First seen on a large Expo/Metro monorepo that forced hoisted for in-tree resolve and ended up with many physicaleffecttrees under workspace packages. Docs: https://aube.jdx.dev/package-manager/node-modules, https://aube.jdx.dev/package-manager/workspaces Upstream discussion: jdx/aube#1242 Upstream fix: jdx/aube#1243 -
pnpm-patch-edit-stale-lock-hash(observed with aube1.36.0, fixed in aube1.37.0, retested on1.37.0): after a declared patch file's content changed, frozen installs used to accept the stale lockfile silently while a plain install applied the new patch but retained the old content hash. Frozen installs now reject the drift withERR_AUBE_LOCKFILE_CONFIG_MISMATCH, and a plain install applies the revised patch and refreshes the lockfile hash. Upstream discussion: jdx/aube#1197 Upstream fix: jdx/aube#1196 -
pnpm-patch-commit-existing-patch(observed with aube1.36.0, fixed in aube1.37.0, retested on1.37.0):aube patch-commitfor an already-patched package used to replace the declared patch with an incremental-only diff that could not apply to pristine package contents. It now reuses the existing patch path and composes the old patch with the new edits, producing a patch that survives a clean reinstall. Upstream discussion: jdx/aube#1195 Upstream fix: jdx/aube#1196 -
pnpm-user-npmrc-allowbuilds-read-only(observed with aube1.32.0and1.34.0, fixed in aube1.35.0, retested on1.36.0):aube config get allowBuildsused to report a value from the user-level~/.npmrcthataube installthen ignored, so the documented way to check the setting confirmed a configuration that had no effect. The same allowlist inpackage.json#aube.allowBuildswas always honored. Install only trusts project-scopedallowBuildsby design; the fix filters.npmrcrows from config inspection for settings that do not declare that source, soconfig getnow returnsundefinedfor a user.npmrcallowlist. Follow-up to the write half raised in #617. Upstream discussion: jdx/aube#1158 Upstream fix: jdx/aube#1159 -
pnpm-filter-add-prunes-platform-optionals(observed with aube1.32.0and1.34.0, fixed in aube1.35.0, retested on1.36.0): in a workspace whosesupportedArchitectureslists includecurrent,aube --filter <pkg> addused to drop every foreign-platform optional dependency from a pnpm lockfile (45 esbuild platform entries to 0 on1.34.0). Portable lockfiles now keep every platform variant while fetch/link still honorsupportedArchitectures. The repro passes--allow-low-downloadsso aube's post-1.35 similar-name gate onis-odddoes not block the add under test. Related to #938 / #942 for the npm lockfile path. Upstream discussion: jdx/aube#1155 Upstream fix: jdx/aube#1156 -
pnpm-file-dep-stale-store(observed with aube1.26.0, fixed in aube1.28.0): a settled workspace with a nestedfile:./modules/...dependency kept serving a stale store copy undernode_modules/.aube/<name>@file+<path-hash>/after the source directory changed on disk. Native pnpm re-added and refreshed the installed content from the same state. Aube now fingerprints local directory dependency contents before taking the warm "Already up to date" path. Docs: https://aube.jdx.dev/package-manager/dependencies, https://aube.jdx.dev/pnpm-users Upstream discussion: jdx/aube#1030 Upstream fix: jdx/aube#1034 -
pnpm-patch-reresolve-drop(observed with aube1.26.0, fixed in aube1.28.0): a non-frozenaube installthat re-resolved because of unrelated manifest drift lost pnpm-compatible patch metadata for a still-declared patch. Later aube builds restored the top-level entry but still dropped(patch_hash=...)identities, so a subsequent native pnpm--frozen-lockfileinstall failed. Aube now preserves or derives pnpm patch hashes on re-resolve. Docs: https://aube.jdx.dev/package-manager/lockfiles, https://aube.jdx.dev/pnpm-users Upstream discussion: jdx/aube#1029 Upstream fix: jdx/aube#1035 -
pnpm-patch-stale-lock-path(observed with aube1.26.0, also reproduced on1.25.2, fixed in aube1.27.0): a non-frozenaube installfailed reading a stalepatchedDependenciespath from the committed lockfile after the workspace moved to a different patch key and deleted the old patch file. Native pnpm re-resolved and applied the current patch from the same state. Fresh re-resolutions now replace the overlaid patch map with the current workspace declarations. Docs: https://aube.jdx.dev/package-manager/lockfiles, https://aube.jdx.dev/pnpm-users Upstream discussion: jdx/aube#1019 Upstream fix: jdx/aube#1022 -
pnpm-patch-plain-unified-diff(observed with aube1.26.0, also reproduced on1.25.2, fixed in aube1.27.0): aube's patch applier only recognized file sections introduced by adiff --githeader line. Plain unified diffs starting with---/+++failed withpatch section missing file path. Native pnpm applied the same patch from the samepatchedDependenciesentry. Aube now accepts plain unified diffs as well. Docs: https://aube.jdx.dev/cli/patch-commit, https://aube.jdx.dev/pnpm-users Upstream discussion: jdx/aube#1018 Upstream fix: jdx/aube#1021 -
pnpm-bin-workspace-flag(observed with aube1.23.0, fixed in aube1.26.0): pnpm'sbin -wprints the workspace-rootnode_modules/.binfrom a workspace package. Aube already supported the long--workspace-rootglobal flag, and now accepts-w,--workspace-root, and--workspacedirectly onaube bin. The repro confirmsaube bin -wmatches native pnpm's output from a workspace package. Docs: https://aube.jdx.dev/cli/bin.html, https://aube.jdx.dev/pnpm-users.html Upstream discussion: jdx/aube#988 Upstream fix: jdx/aube#993 -
global-outdated-packages(observed with aube1.21.0, fixed in aube1.23.0): aube supports global package installs and global updates, butaube outdated -gwas rejected with an unexpected argument error instead of checking globally installed packages. The repro installsis-positive@1.0.0into an isolated aube global directory, confirms the package is globally listed, and then showsaube outdated -greports the stale global version. aube returns exit code1when outdated globals exist, matching npm-style outdated semantics. Docs: https://aube.jdx.dev/package-manager/dependencies.html, https://aube.jdx.dev/cli/outdated Upstream fix: jdx/aube#910 -
dlx-allow-build-flag(observed with aube1.18.0, fixed in aube1.18.2):aube dlx --allow-build=esbuild vite --versiontreated--allow-build=esbuildas the package to execute and failed with an invalid package-name registry error. pnpm11.3.0accepts the samedlxflag, and pnpm documentspnx,pnpm dlx, andpnpxas aliases that support--allow-buildfor allowing named packages to run postinstall scripts during the temporary install. Docs: https://pnpm.io/cli/pnx, https://aube.jdx.dev/package-manager/lifecycle-scripts, https://aube.jdx.dev/cli/add -
bun-patched-dependencies(observed with aube1.14.1, fixed in aube1.15.0): aube installs from Bun's textbun.lock, but it does not apply Bun's top-levelpatchedDependenciesmanifest field. Native Bun applies the patch from the same manifest and lockfile. Aube documents patch support throughaube.patchedDependencies/pnpm.patchedDependencies, but the Bun rollout docs do not mention Bun's top-level field. Docs: https://aube.jdx.dev/package-manager/configuration, https://aube.jdx.dev/bun-users Upstream discussion: jdx/aube#722 -
bun-workspace-link(observed with aube1.13.1, fixed in aube1.14.1): aube installs from Bun's textbun.lock, but a workspace dependency symlink insidepackages/apppoints to the workspace root instead ofpackages/contracts. Upstream discussion: jdx/aube#691 -
npm-lock-missing-entry(observed with aube1.14.0, fixed in aube1.14.1): aube repairs a stale npmpackage-lock.jsonby adding the rootexpo-routerdependency spec, but it does not addpackages["node_modules/expo-router"]. A clean frozen aube install then omitsnode_modules/expo-router. The stale npm lock was produced by npm11.14.1from the same manifest beforeexpo-routerwas added, usingnpm install --package-lock-only --ignore-scripts --no-audit --no-fund. Upstream discussion: jdx/aube#690 -
yarn-hoisted-transitive-dependency(observed with aube1.14.1, fixed in aube1.15.0): aube hoisted mode installs from a Yarn v1yarn.lock, but the materialized dependency tree does not makemagic-string's declared dependencysourcemap-codecresolvable frommagic-string. Native Yarn v1.22.22 installs the same lockfile with that dependency resolvable. This was first seen through areact-scripts@5.0.0hoisted-mode failure onreact-dev-utils/crossSpawn, but reduces to this smaller transitive dependency case. The repro disables aube's global virtual store so unrelated cached installs cannot mask the missing dependency. Docs: https://aube.jdx.dev/package-manager/node-modules, https://aube.jdx.dev/package-manager/lockfiles, https://aube.jdx.dev/troubleshooting Upstream discussion: jdx/aube#725 -
yarn-scoped-dependency-linking(observed with aube1.14.1, fixed in aube1.15.0): aube installs from a Yarn v1yarn.lock, but the materialized dependency tree does not make@rollup/plugin-replace's declared dependency@rollup/pluginutilsresolvable from@rollup/plugin-replace. Native Yarn v1.22.22 installs the same lockfile with that dependency resolvable. This was first seen through areact-scripts@5.0.0build failure involvingworkbox-build, but reduces to this smaller scoped-dependency case. The repro disables aube's global virtual store so unrelated cached installs cannot mask the missing scoped dependency. Docs: https://aube.jdx.dev/package-manager/node-modules, https://aube.jdx.dev/package-manager/lockfiles, https://aube.jdx.dev/troubleshooting Upstream discussion: jdx/aube#723
package-config-symlink-resolution(observed with aube1.15.0, still present with aube1.37.0in default isolated mode): aube installs a package whose config file requires one of that package's declared dependencies, but loading that config through the package's top-levelnode_modules/<pkg>symlink cannot resolve the declared dependency. Loading the same file throughfs.realpathSyncsucceeds because Node's resolver then starts inside the aube virtual-store package directory. This was first seen through Expo / React Native autolinking, whereexpo'sreact-native.config.jsrequiresexpo-modules-autolinking/exports; if that config load fails, autolinking falls back to parsing native sources and generates an invalidexpo.core.ExpoModulesPackageimport. The reduced repro also fails with pnpm11.1.3, so this is an isolated symlink layout compatibility edge rather than an aube-only divergence from pnpm. Mitigated byaube install --node-linker=hoisted, and by aubeshim for npm-shaped local commands, which runs npm-shimmed aube invocations withAUBE_NODE_LINKER=hoistedunless the caller already selected a node linker. Upstream discussion: jdx/aube#754install-omit-optional(observed with aube1.14.1, still present with aube1.37.0): aube rejectsaube install --omit optionalwith an unexpected argument error. This blocks npm/Bun-compatible production install commands that use--omit optional; aube's documented equivalent is--no-optional. Mitigated in aubeshim, which translates npm/Bun--omit optionalto aube--no-optionaland npm/Bun--omit devto aube--prod. Docs: https://aube.jdx.dev/package-manager/install
Each case has a repro.sh script that exits zero when aube behaves correctly
and non-zero when the issue is observed.