Skip to content

fix default export#4141

Draft
huseeiin wants to merge 2 commits intonitrojs:mainfrom
huseeiin:fix-default-export
Draft

fix default export#4141
huseeiin wants to merge 2 commits intonitrojs:mainfrom
huseeiin:fix-default-export

Conversation

@huseeiin
Copy link
Contributor

@huseeiin huseeiin commented Mar 22, 2026

in dev nitro doesn't complain if there is no default export in server.ts, this fixes it in prod.

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@huseeiin huseeiin requested a review from pi0 as a code owner March 22, 2026 13:56
@vercel
Copy link

vercel bot commented Mar 22, 2026

@huseeiin is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Mar 22, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ad3a99ae-3e0a-429d-a792-58b9e04772c0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Non-lazy route handlers in the routing template are now imported dynamically with top-level await instead of static ESM imports. Import failures are caught and handled gracefully. Lazy handlers using h3.defineLazyEventHandler remain unchanged.

Changes

Cohort / File(s) Summary
Route Handler Import Pattern
src/build/virtual/routing.ts
Replaced static ESM imports for non-lazy route handlers with dynamic imports using top-level await and catch error handling, allowing runtime resolution with graceful failure handling instead of module linking failures.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'fix default export' does not follow conventional commits format, which requires a type prefix like 'fix:', 'feat:', 'docs:', etc. Update the title to follow conventional commits format, e.g., 'fix: default export handling in production builds'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description explains the issue being fixed (dev vs prod behavior for missing default exports) and is related to the changeset, though minimal detail is provided.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Tip

You can enable review details to help with troubleshooting, context usage and more.

Enable the reviews.review_details setting to include review details such as the model used, the time taken for each step and more in the review comments.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/build/virtual/routing.ts`:
- Around line 33-36: The generated import line currently swallows all import
errors via .catch(() => {}) and then destructures default into ${h._importHash},
which hides whether the import failed or returned no default; change the
generated code so you import into a module variable (e.g., const mod = await
import("${h.handler}").catch((e) => { throw new Error(`Failed to import handler
${h.handler}: ${e?.message||e}`); });), then explicitly validate that mod &&
mod.default exists before assigning to ${h._importHash} and if not throw a clear
error mentioning the handler path and import hash (use h.handler and
h._importHash) so failures surface with actionable context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6fe85968-df96-444c-9193-6e48a7175de6

📥 Commits

Reviewing files that changed from the base of the PR and between 8e8fdd0 and 1b13f32.

📒 Files selected for processing (1)
  • src/build/virtual/routing.ts

Comment on lines +33 to +36
.map(
(h) =>
/* js */ `const { default: ${h._importHash} } = await import("${h.handler}").catch(() => {})`
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

node --input-type=module <<'EOF'
const noDefault = await import('data:text/javascript,export const handler = () => {}');
console.log('default in namespace:', 'default' in noDefault, 'value:', noDefault.default);

try {
  const { default: handler } = await import('data:text/javascript,throw new Error("boom")').catch(() => {});
  console.log('handler:', handler);
} catch (error) {
  console.error('error after catch:', error.message);
}
EOF

Repository: nitrojs/nitro

Length of output: 221


🏁 Script executed:

cd src/build/virtual && [ -f routing.ts ] && cat -n routing.ts | head -50

Repository: nitrojs/nitro

Length of output: 2158


🏁 Script executed:

rg "\.catch\(\(\)" src/build/virtual/routing.ts -A 2 -B 2

Repository: nitrojs/nitro

Length of output: 194


🏁 Script executed:

git ls-files src/build/virtual/

Repository: nitrojs/nitro

Length of output: 506


🏁 Script executed:

rg "\.catch\s*\(\s*\(\s*\)\s*=>\s*\{\s*\}" src/build --type ts

Repository: nitrojs/nitro

Length of output: 185


🏁 Script executed:

rg "await import.*catch" src/build --type ts -A 1 -B 1

Repository: nitrojs/nitro

Length of output: 258


🏁 Script executed:

rg "handler.*import" src/build/virtual/routing.ts -A 2 -B 2

Repository: nitrojs/nitro

Length of output: 39


🏁 Script executed:

git log --oneline src/build/virtual/routing.ts | head -5

Repository: nitrojs/nitro

Length of output: 83


🏁 Script executed:

git show 1b13f32 --stat

Repository: nitrojs/nitro

Length of output: 50369


🏁 Script executed:

git show 1b13f32 -- src/build/virtual/routing.ts | head -80

Repository: nitrojs/nitro

Length of output: 2734


Don't silently swallow handler import failures with .catch(() => {}).

Line 35 suppresses import errors and leaves the destructuring to fail later with an opaque message. When import() succeeds but has no default export, the destructuring still fails downstream without context about which handler path failed. This violates the coding guideline to prefer explicit errors and include actionable context.

Validate mod.default explicitly after import and throw with the handler path included:

Proposed fix
 ${allHandlers
   .filter((h) => !h.lazy)
   .map(
-    (h) =>
-      /* js */ `const { default: ${h._importHash} } = await import("${h.handler}").catch(() => {})`
+    (h) =>
+      /* js */ `
+const ${h._importHash}Module = await import("${h.handler}").catch((error) => {
+  throw new Error(${JSON.stringify(`Failed to import route handler "${h.handler}"`)} + ": " + String(error));
+});
+if (${h._importHash}Module.default === undefined) {
+  throw new Error(${JSON.stringify(`Route handler "${h.handler}" must have a default export`)});
+}
+const ${h._importHash} = ${h._importHash}Module.default;`
   )
   .join("\n")}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.map(
(h) =>
/* js */ `const { default: ${h._importHash} } = await import("${h.handler}").catch(() => {})`
)
.map(
(h) =>
/* js */ `
const ${h._importHash}Module = await import("${h.handler}").catch((error) => {
throw new Error(${JSON.stringify(`Failed to import route handler "${h.handler}"`)} + ": " + String(error));
});
if (${h._importHash}Module.default === undefined) {
throw new Error(${JSON.stringify(`Route handler "${h.handler}" must have a default export`)});
}
const ${h._importHash} = ${h._importHash}Module.default;`
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/build/virtual/routing.ts` around lines 33 - 36, The generated import line
currently swallows all import errors via .catch(() => {}) and then destructures
default into ${h._importHash}, which hides whether the import failed or returned
no default; change the generated code so you import into a module variable
(e.g., const mod = await import("${h.handler}").catch((e) => { throw new
Error(`Failed to import handler ${h.handler}: ${e?.message||e}`); });), then
explicitly validate that mod && mod.default exists before assigning to
${h._importHash} and if not throw a clear error mentioning the handler path and
import hash (use h.handler and h._importHash) so failures surface with
actionable context.

@huseeiin huseeiin marked this pull request as draft March 22, 2026 14:23
@huseeiin
Copy link
Contributor Author

@pi0 coderabbitai is right, this ignores all errors. what should we do?

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.

1 participant