Skip to content

docs: refresh the 1.4 upgrade guide for changes landed since August 12 - #39445

Merged
alii merged 3 commits into
farm/6f9ff460/docs-upgrade-guide-1.4from
farm/47b4aeb3/upgrade-guide-refresh
Aug 17, 2026
Merged

alii merged 3 commits into
farm/6f9ff460/docs-upgrade-guide-1.4from
farm/47b4aeb3/upgrade-guide-refresh

Conversation

@robobun

@robobun robobun commented Aug 17, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #36463 (the base branch is that PR's branch, so the diff here is only the additions). Merging this into #36463 adds the behavior changes listed below; #36463 itself now covers the #38333 install batch, the optional-peer correction, and the TOML / bun init fixes, so this PR no longer touches those.

Problem

Fix

  • Adds a MySQL public key section (plus a summary table row), a TLS note under the PGSSLMODE section, an .npmrc / credentials addendum to the bunfig.toml section, a module.enableCompileCache() section, and the rest as bullets in the existing lists.
  • docs/pm/overrides.mdx: one-line change adding a pointer to this guide in the existing lockfileVersion 3 limitation. (The base branch briefly had a duplicate "Nested overrides" section; it removed that itself in 8257d01acb, and this PR was rebased over it.)
  • Verification: each runtime claim was run against 1.4.0-canary.1+8326d1bd3 (22 commits behind main; contains every change referenced), and each install or bundler claim was checked against the source on main, with the 1.3 side taken from the bun-v1.3.14 tag where the PR body did not state it. The /runtime/sql#mysql and /upgrade-to-1.4 links resolve. prettier --check passes.

Not included on purpose

Commands used to verify the runtime claims
timers/promises setTimeout with an aborted signal             # "The operation was aborted"
bun req.cjs                                                   # Cannot find module ... Require stack:
bun b.mjs (import() of a missing package / relative file)      # Cannot find package 'x' imported from /path, ERR_MODULE_NOT_FOUND
bun a_static.mjs (unhandled static import)                    # printed line still: Cannot find package 'x' from '/path'
process.versions.icu                                          # 78.3
createCipheriv("aes-128-gcm", key, Buffer.alloc(129))         # ERR_CRYPTO_INVALID_IV
DecompressionStream of a 1 MiB gzip member                    # 16 chunks of 65536 bytes
new SQL("sqlite://:memory:") with ${[1,2]} / ${new Date()}    # Binding expected ...
fs.mkdtempSync("")                                            # EINVAL
vm.runInThisContext("1", [])                                  # ERR_INVALID_ARG_TYPE
NODE_COMPILE_CACHE=/tmp/cc bun cc.cjs                         # creates /tmp/cc/v1.4.0-x86_64-<sha>-<uid>
NODE_DISABLE_COMPILE_CACHE=1 + enableCompileCache()           # status 3 (DISABLED)
bun dedupe / bun up with package.json scripts of those names  # built-in command runs
bun feedback                                                  # Script not found "feedback"
Bun.build({ splitting: true, format: "cjs" })                 # Code splitting is currently only supported ...
bun build of a function-scoped enum and import * as ns         # let Color; exports a, m, z
new SQL({ url: "postgres://...", tls: true }) on a non-TLS server  # ERR_POSTGRES_TLS_NOT_AVAILABLE
Bun.TOML.parse("a = 9007199254740993")                        # Integer cannot be losslessly represented ...
Previous revision

The first revision of this PR (3c5611454a) also rewrote the package manager section for #38333 / #38853 (nested overrides and lockfileVersion: 3, the optional-peer correction, bun update, bunfig.toml over .npmrc, --filter) and fixed the TOML date and bun init lines. #36463 picked those up in its own commits the same day, so this PR was rebased onto its new head and reduced to the items above.


no test proof · iteration 0 · docs-only change; test-proof not applicable

@claude claude 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.

Additional findings (outside current diff — PR may have been updated during review):

  • 🔴 docs/upgrade-to-1.4.mdx:68 — The two links here — [nested rules](/pm/overrides#nested-overrides) and [version-scoped keys](/pm/overrides#version-scoped-overrides) — point at anchors that don't exist: docs/pm/overrides.mdx has only ## "overrides" and ## "resolutions". Worse, that page still says "Bun only supports top-level "overrides", not nested" (line 49) and "nested resolutions are not supported" (line 70), directly contradicting this section. Either update docs/pm/overrides.mdx in this PR (add the sections and drop the "not supported" notes) and link to the real headings, or drop the anchors and link to /pm/overrides until those sections exist.

    Extended reasoning...

    What the bug is

    docs/upgrade-to-1.4.mdx:68 introduces two internal links:

    Bun 1.4 also applies [nested rules](/pm/overrides#nested-overrides) (npm's object form, ...) and [version-scoped keys](/pm/overrides#version-scoped-overrides), ...

    Neither anchor exists. Reading docs/pm/overrides.mdx on this branch, the file has exactly two headings — ## "overrides" (line 44) and ## "resolutions" (line 66). There is no #nested-overrides heading and no #version-scoped-overrides heading. git log -- docs/pm/overrides.mdx shows the file is untouched by this PR and its base branch, so nothing upstream is adding those sections either.

    The second half of the problem is worse than a dead anchor: the target page still documents the pre-1.4 behavior. Lines 48-51:

    Bun only supports top-level "overrides", not nested overrides.

    and line 70:

    As with "overrides", nested resolutions are not supported.

    So the upgrade guide tells the reader "Bun 1.4 now applies nested and version-scoped overrides", links them to /pm/overrides for the details, and that page tells them the opposite.

    Why existing checks didn't catch it

    The PR description states "Internal links resolve to pages and headings that exist on main", but that verification evidently checked page paths, not fragment anchors — /pm/overrides exists, #nested-overrides on it does not. Mintlify does not fail the build on a fragment that resolves to no heading; the link simply scrolls nowhere. prettier --check (the only check the description mentions running) does not validate anchors.

    Step-by-step proof

    1. Open docs/upgrade-to-1.4.mdx at line 68 on this branch: the two links target /pm/overrides#nested-overrides and /pm/overrides#version-scoped-overrides.
    2. grep -n '^##' docs/pm/overrides.mdx on this branch:
      44:## "overrides"
      66:## "resolutions"
      
      Neither target heading exists, so both fragments are dead.
    3. sed -n '48,51p;70p' docs/pm/overrides.mdx shows the two "not supported" statements quoted above — the linked page contradicts the upgrade guide.
    4. git log --oneline -- docs/pm/overrides.mdx shows no commit on this branch or its base touching the file, so merging this PR ships the contradiction.

    Impact

    A reader following either link from the 1.4 upgrade guide lands at the top of /pm/overrides (the fragment matches nothing, so the browser doesn't scroll), reads down, and is told nested overrides are not supported — the exact opposite of what the guide just said. For a page whose purpose is to explain what changed in 1.4, that's actively misleading, not just cosmetic.

    The repo's own docs guidance (.claude/docs/landing-prs.md, "Docs, types, and comments") says: "Sweep the same PR for everything describing the old state ... A comment contradicting the code is a correctness bug, not a nit" and "fetch every URL". This PR's whole purpose is that sweep, and overrides.mdx is squarely inside it.

    How to fix

    Preferred: update docs/pm/overrides.mdx in this PR — remove the two "not supported" notes and add ### Nested overrides and ### Version-scoped overrides sections (or whatever headings you want the anchors to be), then point the two links here at those real slugs.

    Minimal: drop the fragments and link both to plain /pm/overrides, and delete the two "not supported" statements from that page so it at least stops contradicting the guide. The detailed sections can follow later.

@robobun

robobun commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

The two anchors flagged here were in the first revision of this PR (3c5611454a), which was based on the guide branch before it was rebased. The current diff no longer contains that section: the base branch (#36463, now at 701b3e2a0) carries its own overrides section and the link /pm/overrides#nested-overrides, and since the rebase the base includes main's docs/pm/overrides.mdx from #38333, which has ## Nested overrides and ## Version-scoped overrides headings and no longer contains the "not supported" notes.

Checking this did turn up a related problem on the base branch: it also added a second ## Nested overrides section to docs/pm/overrides.mdx ahead of main's, so the page had two headings with that name and the anchor was ambiguous. ee13c73da8 removes the duplicate and keeps the cross-references and the upgrade-guide pointer (moved into the existing lockfileVersion 3 limitation). Relative to main, overrides.mdx now only gains three sentences; grep '^#' docs/pm/overrides.mdx on this branch lists each heading once.

Comment thread docs/upgrade-to-1.4.mdx Outdated
@robobun

robobun commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

Right, the "unchanged" clause was wrong. Checked on the current build: for both import statements and import(), error.message is now Cannot find package 'x' imported from /path (Cannot find module './x' imported from /path for a relative specifier), where 1.3 produced Cannot find package 'x' from '/path'; ResolveMessage::node_message() reshapes .message, .stack, and String(err) for both kinds. The line Bun itself prints for an unhandled resolution error still reads Cannot find package 'x' from '/path' for both require() and import, which is what the earlier check had looked at.

One correction to the review: the code for import / import() did not change. test/js/node/missing-module.test.js asserted ERR_MODULE_NOT_FOUND on the import() cases before #34660 as well (the diff in that commit only touches the message lines), and 1.3.14 reports the same code. b8dc487de1 rewrites the bullet to describe both message changes, says the codes and the printed line are unchanged, and the PR description's verification list now includes the import() and static-import checks.

@claude claude 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.

LGTM — the module-not-found bullet was rewritten in b8dc487d to cover both require() and import/import() message changes, and now matches ResolveMessage::node_message() (including the note that the code values did not change, which corrects my earlier remark). docs/pm/overrides.mdx has each heading once, so the #nested-overrides / #version-scoped-overrides anchors resolve unambiguously.

Extended reasoning...

Overview

Docs-only change to two files: docs/upgrade-to-1.4.mdx gains ~20 new behavior-change entries (MySQL public-key retrieval, TLS enforcement, .npmrc / registry-credential precedence, module.enableCompileCache(), module-not-found messages, AbortError wording, GCM IV length, mkdtemp(""), vm options, ICU 78, compression-stream chunking, SQLite bindings, server.reload, bundler splitting/enum/export-order/minify-$, and CLI outdated/dedupe/up/workspace:/isolated-store items), plus a summary-table row and a wording tweak to the TOML integer bullet. docs/pm/overrides.mdx drops the duplicate "Nested overrides" section the base branch added and folds the upgrade-guide pointer into the existing lockfileVersion 3 limitation.

Follow-up on prior review

My earlier inline finding (the "messages for import and import() are unchanged" clause) was addressed in b8dc487d. I re-checked the rewritten bullet against src/jsc/ResolveMessage.rs:392-413: the require() form (Cannot find module 'x' + Require stack:) and both import forms (Cannot find package 'x' imported from ... / Cannot find module './x' imported from ...) match, and the author is correct that the code values were already MODULE_NOT_FOUND / ERR_MODULE_NOT_FOUND in 1.3, so "unchanged" is accurate there. I also confirmed docs/pm/overrides.mdx now lists each ## heading exactly once.

Security risks

None. Pure documentation; no executable code, config, or CI changes.

Level of scrutiny

Medium — factual accuracy matters for an upgrade guide, but the author documented per-claim verification against 1.4.0-canary.1+8326d1bd3 and the bun-v1.3.14 tag, cited the source PR for each item, and responded precisely to the one factual error found in the prior pass (including correcting a detail I had wrong). This run's bug hunt found nothing further.

Other factors

Stacked on #36463, so this merges into that branch rather than main. The overrides dedup is defensive against a rebase artifact and leaves the page with three added sentences relative to main. prettier --check reportedly passes.

MySQL public key retrieval now refused by default, tls/ssl options
requiring TLS, ~/.npmrc fallback and registry URL credentials,
module.enableCompileCache() being implemented, the require() not-found
and AbortError messages, GCM IV validation, mkdtemp and vm validation,
server.reload, ICU 78, Compression stream chunking, the Bun.SQL sqlite
binding change, splitting with cjs/iife being an error, transpiler output
differences, bun outdated exit codes, the dedupe/up commands, workspace:
ranges in downloaded packages, and isolated store entry names.
import and import() failures now read "imported from" in error.message
as well; only the codes and Bun's printed line are unchanged.
@robobun
robobun force-pushed the farm/47b4aeb3/upgrade-guide-refresh branch from b8dc487 to de55df7 Compare August 17, 2026 16:30
@robobun

robobun commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto the base branch's current head (8257d01acb, which removed the duplicate overrides section on its own a few minutes before this PR did the same). The overrides page change here is now a single sentence, the pointer to this guide in the existing lockfileVersion 3 limitation; the upgrade guide diff is unchanged (de55df787b).

@claude claude 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.

The prior finding on the module-not-found bullet is addressed — it now covers the import / import() wording change and correctly states the codes are unchanged. No new issues found on this revision. Given this adds ~20 distinct factual claims about 1.3→1.4 behavior across install, SQL, runtime, and bundler, a maintainer familiar with the 1.4 release scope should still give it a read for coverage and phrasing.

Checked: the rewritten not-found bullet against ResolveMessage::node_message() and missing-module.test.js; the /upgrade-to-1.4 link from overrides.mdx and the #mysql anchor; that overrides.mdx has no duplicate headings after the rebase; the summary-table row lines up with its section.

Extended reasoning...

Overview

Docs-only change to two files: docs/upgrade-to-1.4.mdx gains a MySQL public-key-retrieval section (plus summary-table row), a module.enableCompileCache() section, an .npmrc/credentials addendum, a TLS-required note under the Postgres section, and roughly fifteen new bullets across the Node-compat / Bun-APIs / bundler / CLI lists. docs/pm/overrides.mdx gains one sentence pointing the lockfileVersion 3 limitation at the upgrade guide. Stacked on #36463.

Security risks

None — documentation only, no code paths touched.

Level of scrutiny

Medium. There is no runtime risk, but this is user-facing release migration documentation making many specific, verifiable claims (exact error messages, error codes, option names, version numbers). The prior revision contained a factual error in exactly this class ("the messages for import are unchanged"), which was caught and fixed. The author has documented empirical verification for each runtime claim against a 1.4 canary and source-checked the install/bundler claims, which raises confidence, but the sheer breadth (MySQL auth, ICU versions, GCM IV limits, isolated-linker store names, enum lowering, etc.) is more than an automated pass can fully fact-check.

Other factors

  • My prior inline finding was addressed in b8dc487de1; the author also correctly pushed back on the sub-claim about the import error code changing (it did not — 1.3 already used ERR_MODULE_NOT_FOUND), and the current text reflects that.
  • The bug-hunting pass on this revision found nothing.
  • The overrides.mdx duplicate-heading issue was resolved on the base branch and this PR was rebased over it; the current file lists each heading once.
  • Because this merges into #36463 rather than main, a human will review the combined guide there regardless; deferring here keeps that loop intact without blocking.

@robobun

robobun commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

Nothing further to change from this pass. Current state for whoever reads the combined guide on #36463: head de55df787b is green and merges cleanly into the base branch, which has not moved since the last rebase. The two points that need a product decision rather than a docs edit are listed under "Not included on purpose" in the description: the lifecycle npm_package_* variables and transitive "*" deduplication (open fixes #36690, #38110, #38770, otherwise each needs a line here), and the Postgres sslmode=prefer / allow hang against servers without SSL, which is filed separately.

@alii
alii merged commit 28eea14 into farm/6f9ff460/docs-upgrade-guide-1.4 Aug 17, 2026
5 checks passed
@alii
alii deleted the farm/47b4aeb3/upgrade-guide-refresh branch August 17, 2026 16:50
Comment thread docs/upgrade-to-1.4.mdx
robobun added a commit that referenced this pull request Aug 17, 2026
…pgrade guide

The guide covers migration steps; narrow validation changes (GCM IV
length, mkdtemp(""), vm options, server.reload, isolated store entry
names, registry URL credentials) are tracked in #28792 instead.
@robobun

robobun commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

Agreed. Since this PR was merged into the #36463 branch, the trimming happened there: f40d4dd removed the compile cache section, and f24047a drops the other items from this batch that were validation changes rather than migration steps (GCM IV length, mkdtemp(""), node:vm options, server.reload, isolated store entry names, registry URL credentials); those stay on the #28792 tracking list. What remains from this batch is the set with a concrete break or action: MySQL allowPublicKeyRetrieval, SQL tls options no longer falling back to plaintext, the ~/.npmrc lookup, the error messages tests match on, splitting with cjs / iife failing the build, transpiler output that changes snapshots, bun outdated exit codes, dedupe / up shadowing scripts, and workspace: ranges in registry packages failing to resolve. Happy to cut any of those too.

robobun added a commit that referenced this pull request Aug 21, 2026
#39445)

Stacked on #36463 (the base branch is that PR's branch, so the diff here
is only the additions). Merging this into #36463 adds the behavior
changes listed below; #36463 itself now covers the #38333 install batch,
the optional-peer correction, and the TOML / `bun init` fixes, so this
PR no longer touches those.

### Problem
- These 1.3 to 1.4 behavior changes are not in the guide at `701b3e2a0`:
- MySQL: the first `caching_sha2_password` connection over plain TCP is
refused unless `allowPublicKeyRetrieval: true` (#31129; 1.3.14 requested
the key automatically, `MySQLConnection.zig` in the 1.3.14 tag). SQL
`tls` / `ssl` options now require TLS instead of falling back to
plaintext, and `?ssl=` / `?ssl-mode=` are read (`shared.ts` 1.3.14 only
read `?sslmode=`; #37669).
- Install: `~/.npmrc` fallback when `XDG_CONFIG_HOME` is set (#36289),
credentials in `--registry` / env / bunfig object URLs are sent and
outrank same-host `.npmrc` tokens (#38796, #38824), `bun outdated` exits
1 on fetch failures (#38809), new `dedupe` / `up` commands shadow
scripts of those names and `bun feedback` is removed (#38333, #38444),
`workspace:` ranges inside registry packages (#37669), isolated store
entry names (#39014).
- Runtime: `module.enableCompileCache()` / `NODE_COMPILE_CACHE`
implemented (#34660), `require()` / `import` not-found messages
(#34660), `AbortError` message without the period (#39277; 1.3.14's
`BunCommonStrings.h` has the period), GCM IV length (#34092),
`mkdtemp("")` (#34908), vm options (#38381), `server.reload` (#38697),
ICU 75/73 to 78 (#38013), Compression stream chunking (#38695),
`Bun.SQL` sqlite bindings (#35950).
- Bundler: `splitting` with `cjs` / `iife` is an error (#32685),
block-scoped `enum` lowers to `let` (#34249), exports emitted ascending
instead of descending (#35957; `doStep5.zig` in 1.3.14 used `sortDesc`),
minified `$` (#35668).
- The TOML integer bullet did not say what the limit or the fix is.

### Fix
- Adds a MySQL public key section (plus a summary table row), a TLS note
under the `PGSSLMODE` section, an `.npmrc` / credentials addendum to the
`bunfig.toml` section, a `module.enableCompileCache()` section, and the
rest as bullets in the existing lists.
- `docs/pm/overrides.mdx`: one-line change adding a pointer to this
guide in the existing `lockfileVersion` 3 limitation. (The base branch
briefly had a duplicate "Nested overrides" section; it removed that
itself in `8257d01acb`, and this PR was rebased over it.)
- Verification: each runtime claim was run against
`1.4.0-canary.1+8326d1bd3` (22 commits behind main; contains every
change referenced), and each install or bundler claim was checked
against the source on main, with the 1.3 side taken from the
`bun-v1.3.14` tag where the PR body did not state it. The
`/runtime/sql#mysql` and `/upgrade-to-1.4` links resolve. `prettier
--check` passes.

### Not included on purpose
- Lifecycle scripts no longer receiving `npm_package_name` /
`npm_package_version` / `npm_package_json` / `npm_config_local_prefix`
during `bun install`, and transitive `"*"` ranges no longer
deduplicating onto the root's version: regressions with open fixes
(#36690, #38110, #38770). They need either the fixes or a guide line
before release.
- Postgres `sslmode=prefer` / `allow` (including `PGSSLMODE=prefer`,
which 1.4 newly reads) hangs until the connection timeout against a
server without SSL because nothing sends the startup message after the
`N` reply. Same code in 1.3.14; filed as a bug instead of documented.

<details>
<summary>Commands used to verify the runtime claims</summary>

```
timers/promises setTimeout with an aborted signal             # "The operation was aborted"
bun req.cjs                                                   # Cannot find module ... Require stack:
bun b.mjs (import() of a missing package / relative file)      # Cannot find package 'x' imported from /path, ERR_MODULE_NOT_FOUND
bun a_static.mjs (unhandled static import)                    # printed line still: Cannot find package 'x' from '/path'
process.versions.icu                                          # 78.3
createCipheriv("aes-128-gcm", key, Buffer.alloc(129))         # ERR_CRYPTO_INVALID_IV
DecompressionStream of a 1 MiB gzip member                    # 16 chunks of 65536 bytes
new SQL("sqlite://:memory:") with ${[1,2]} / ${new Date()}    # Binding expected ...
fs.mkdtempSync("")                                            # EINVAL
vm.runInThisContext("1", [])                                  # ERR_INVALID_ARG_TYPE
NODE_COMPILE_CACHE=/tmp/cc bun cc.cjs                         # creates /tmp/cc/v1.4.0-x86_64-<sha>-<uid>
NODE_DISABLE_COMPILE_CACHE=1 + enableCompileCache()           # status 3 (DISABLED)
bun dedupe / bun up with package.json scripts of those names  # built-in command runs
bun feedback                                                  # Script not found "feedback"
Bun.build({ splitting: true, format: "cjs" })                 # Code splitting is currently only supported ...
bun build of a function-scoped enum and import * as ns         # let Color; exports a, m, z
new SQL({ url: "postgres://...", tls: true }) on a non-TLS server  # ERR_POSTGRES_TLS_NOT_AVAILABLE
Bun.TOML.parse("a = 9007199254740993")                        # Integer cannot be losslessly represented ...
```

</details>

<details>
<summary>Previous revision</summary>

The first revision of this PR (`3c5611454a`) also rewrote the package
manager section for #38333 / #38853 (nested overrides and
`lockfileVersion: 3`, the optional-peer correction, `bun update`,
`bunfig.toml` over `.npmrc`, `--filter`) and fixed the TOML date and
`bun init` lines. #36463 picked those up in its own commits the same
day, so this PR was rebased onto its new head and reduced to the items
above.

</details>

<!-- robobun:evidence:begin -->

---

**no test proof** · iteration 0 · docs-only change; test-proof not
applicable

<!-- robobun:evidence:end -->
robobun added a commit that referenced this pull request Aug 21, 2026
…pgrade guide

The guide covers migration steps; narrow validation changes (GCM IV
length, mkdtemp(""), vm options, server.reload, isolated store entry
names, registry URL credentials) are tracked in #28792 instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants