Skip to content

fix: run close hooks once per nitro instance - #4835

Merged
pi0 merged 1 commit into
mainfrom
fix/idempotent-close
Oct 18, 2026
Merged

pi0 merged 1 commit into
mainfrom
fix/idempotent-close

Conversation

@pi0x

@pi0x pi0x commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

With the vite builder, nitro build ran close hooks twice: buildEnvironments closes nitro after the server bundle, then the CLI closes it again. nitro.close() had no guard, so any close hook (from config or modules) ran on every call.

nitro.close() now caches its promise, so repeated or concurrent calls run the hooks once. Tests cover it with a unit test and the existing vite nitro build fixture, which now also logs close.

🤖 Generated with AI assistant

The vite builder closes nitro after the server bundle, and `nitro build`
closed it again, so `close` hooks ran twice. `nitro.close()` now
returns the same promise on repeated calls.
@pi0x
pi0x requested a review from pi0 as a code owner October 18, 2026 02:07
@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nitro.build Ready Ready Preview Oct 18, 2026 2:07am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 49f639a6-1d95-4af4-bcfe-05d5570e6db0
📥 Commits

Reviewing files that changed from the base of the PR and between 8a6b16f and 456a63f.

📒 Files selected for processing: 4
  • src/nitro.ts
  • test/unit/nitro-close.test.ts
  • test/vite/cli-build-fixture/nitro.config.ts
  • test/vite/cli-build.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

📝 Walkthrough

Nitro now caches the promise from its first close() call and returns it on subsequent calls. Unit and CLI build tests cover the close-hook invocation and logging.

Changes: Nitro close lifecycle

Layer / File(s) Summary
Cache and verify the close-hook promise
src/nitro.ts, test/unit/nitro-close.test.ts, test/vite/cli-build-fixture/nitro.config.ts, test/vite/cli-build.test.ts
close() retains and returns the first close-hook promise. The unit test checks concurrent and subsequent calls invoke the hook once. The CLI build test checks that close is logged after prerender:init.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 456a6

Repeated close calls should run hooks once. No actionable merge-blocking risk remains after normal checks.

Security architecture risk: 🔵 Low · up to 456a6

The change prevents duplicate cleanup without introducing a demonstrated new trust boundary or privilege. However, a rejected close operation now remains failed for that instance, potentially preventing later cleanup hooks from releasing resources.

Retained concerns

  • Low · reliability · inferred: A rejected first close permanently prevents another hook-dispatch attempt through close() on the same instance. Because hooks execute serially and stop on failure, a transient early-hook error can leave later resource-cleanup callbacks unreached. The base allowed another call to retry dispatch. This affects cleanup ownership and failure containment; it does not establish a remote attack path or a documented retry-contract violation.
Security review details

Security Blast Radius

  • inferred — The identified failure-containment exposure is scoped to resources owned by the affected Nitro instance and its host process. The inspected change does not establish cross-tenant propagation, additional credential authority, or a new remotely reachable shutdown entrypoint.

Trust Boundaries and Controls

  • observed — The two specifically signaled test entrypoints are a temporary-project unit test and a configured build fixture. Their changed code exercises existing project-hook execution rather than introducing an authentication decision or accepting network-request data.

Resilience and Maintainability Implications

  • observed — Existing Vite development shutdown already shares a cached close promise. Dev-server cleanup also catches errors from listener, manager, and watcher cleanup operations once reached. These controls limit some failure modes but do not ensure execution of cleanup callbacks skipped after an earlier hook fails.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title follows the Conventional Commits format with the fix: prefix and accurately describes the change to run close hooks once per Nitro instance.
Description check Passed The description accurately explains the duplicate close hook execution, the promise caching fix, and the added test coverage.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Oct 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/nitro@4835

commit: 456a63f

@pi0
pi0 merged commit bf4fe69 into main Oct 18, 2026
15 checks passed
@pi0
pi0 deleted the fix/idempotent-close branch October 18, 2026 02:14

This branch was successfully deployed

1 active deployment
Preview — 456a63f0 Deployed Oct 18, 2026 by vercel[bot]
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.

2 participants