-
Notifications
You must be signed in to change notification settings - Fork 34
Description
Environment
Environment
Operating System: Linux (Ubuntu)
Node Version: v22.14.0
Nuxt Version: 3.16.1
Nitro Version: 2.11.7
Package Manager: npm@10.9.2 (also tested with Bun@1.2.7)
Preset: cloudflare-pages
Compatibility Date: 2025-03-12 (also tested with 2025-03-20)
Reproduction
Nuxt 3.16.1 with Nitro 2.11.7
ℹ Building for Nitro preset: cloudflare-pages
✔ Generated public dist
[nitro] ℹ Building Nuxt Nitro server (preset: cloudflare-pages, compatibility date: 2025-03-12)
[nitro] ERROR Error: ENOTDIR: not a directory, stat '/home/hermes/Projetos-linux/cidadeMobile/node_modules/nitropack/node_modules/unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper'
undefined
[ERROR] ENOTDIR: not a directory, stat '.../unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper'
error: script "build" exited with code 1
Describe the bug
When building a Nuxt 3.16.1 project with Nitro 2.11.7 using the cloudflare-pages preset, the build fails with the following error:
[nitro] ERROR Error: ENOTDIR: not a directory, stat '.../node_modules/nitropack/node_modules/unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper'
The error occurs during the "Building Nuxt Nitro server" step, indicating that unenv (via nitropack) is attempting to treat webidl2js-wrapper as a directory when it should be a file, or the file is missing/corrupted in the unenv@1.10.0 structure. This happens consistently both locally (Ubuntu, Node 22.14.0, Bun 1.2.7 or npm 10.9.2) and on Cloudflare Pages deployment. The issue persists despite forcing unenv@1.10.0 in resolutions and excluding whatwg-url/webidl2js-wrapper in nitro.externals.inline.
I suspect this is a bug in how unenv@1.10.0 structures or resolves whatwg-url.mjs/webidl2js-wrapper for the cloudflare-pages preset. I’m happy to submit a PR if guided on where to start—thanks!
Additional context
import { fileURLToPath } from 'node:url'
import vuetify from 'vite-plugin-vuetify'
import svgLoader from 'vite-svg-loader'
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
runtimeConfig: {
alibabaApiKey: import.meta.env.NUXT_ALIBABA_API_KEY,
public: {
API_BASE_URL: import.meta.env.NUXT_PUBLIC_API_BASE_URL || 'http://localhost:8055',
},
},
features: {
inlineStyles: false,
},
app: {
head: {
titleTemplate: '%s - Cidade Transparente',
title: 'Softagon',
link: [{
rel: 'icon',
type: 'image/x-icon',
href: `/favicon.ico`,
}],
},
},
devtools: {
enabled: false,
},
css: [
'@core/scss/template/index.scss',
'@styles/styles.scss',
'@/plugins/iconify/icons.css',
'notivue/notification.css', // Added Notivue notification styles
'notivue/animations.css', // Added Notivue animations styles
'@mdi/font/css/materialdesignicons.css', // Adicionado para suportar ícones MDI
],
components: [
{
path: '@/@core/components',
pathPrefix: false,
},
{
path: '~/components/global',
global: true,
},
{
path: '~/components',
},
],
plugins: ['@/plugins/vuetify/index.ts', '@/plugins/iconify/index.ts'],
imports: {
dirs: ['./@core/utils', './@core/composable/', './plugins/*/composables/*'],
},
experimental: {
typedPages: true,
},
typescript: {
tsConfig: {
compilerOptions: {
paths: {
'@/*': ['../*'],
'@themeConfig': ['../themeConfig.ts'],
'@layouts/*': ['../@layouts/*'],
'@layouts': ['../@layouts'],
'@core/*': ['../@core/*'],
'@core': ['../@core'],
'@images/*': ['../assets/images/*'],
'@styles/*': ['../assets/styles/*'],
'@validators': ['../@core/utils/validators'],
'@db/*': ['../server/fake-db/*'],
'@api-utils/*': ['../server/utils/*'],
},
},
},
},
vue: {
compilerOptions: {
isCustomElement: tag => tag === 'swiper-container' || tag === 'swiper-slide',
},
},
vite: {
define: { 'process.env': {} },
resolve: {
alias: {
'@': fileURLToPath(new URL('.', import.meta.url)),
'@themeConfig': fileURLToPath(new URL('./themeConfig.ts', import.meta.url)),
'@core': fileURLToPath(new URL('./@core', import.meta.url)),
'@layouts': fileURLToPath(new URL('./@layouts', import.meta.url)),
'@images': fileURLToPath(new URL('./assets/images/', import.meta.url)),
'@styles': fileURLToPath(new URL('./assets/styles/', import.meta.url)),
'@configured-variables': fileURLToPath(new URL('./assets/styles/variables/_template.scss', import.meta.url)),
'@db': fileURLToPath(new URL('./server/fake-db/', import.meta.url)),
'@api-utils': fileURLToPath(new URL('./server/utils/', import.meta.url)),
},
},
plugins: [
svgLoader(),
vuetify({
styles: {
configFile: 'assets/styles/variables/_vuetify.scss',
},
}),
],
// Optimização do build para remover componentes relacionados ao layout horizontal
build: {
rollupOptions: {
external: [
'@layouts/components/HorizontalNav.vue',
'@layouts/components/HorizontalNavGroup.vue',
'@layouts/components/HorizontalNavLayout.vue',
'@layouts/components/HorizontalNavLink.vue',
'@layouts/components/HorizontalNavPopper.vue',
],
},
},
},
build: {
transpile: ['vuetify'],
},
modules: ['@vueuse/nuxt', '@nuxtjs/i18n', '@nuxtjs/device', '@pinia/nuxt', 'notivue/nuxt'],
i18n: {
bundle: {
optimizeTranslationDirective: false,
},
},
notivue: {
pauseOnHover: true,
pauseOnTouch: true,
pauseOnTabChange: true,
enqueue: true,
limit: 3,
position: 'top-center',
notifications: {
global: {
duration: 2500,
},
},
},
nitro: {
preset: 'cloudflare-pages',
prerender: {
crawlLinks: true,
routes: ['/'],
ignore: ['/api', '/servicos/**'],
},
externals: {
inline: ['canva', 'whatwg-url', 'unenv/runtime/npm/whatwg-url', 'webidl2js-wrapper'],
},
minify: false,
buildDir: '.output',
publicAssets: [
{
dir: '.output/public',
maxAge: 60 * 60 * 24 * 365,
},
],
},
compatibilityDate: '2025-03-20',
})
{
"name": "cidade-transparente",
"type": "module",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt dev",
"build": "nuxt build",
"lint": "eslint . -c .eslintrc.cjs --fix --ext .ts,.js,.cjs,.vue,.tsx,.jsx",
"build:icons": "tsx plugins/iconify/build-icons.ts",
"postinstall": "nuxt prepare && npm run build:icons",
"generate": "nuxt generate",
"gen:types": "node directus/scripts/genTypes.ts"
},
"dependencies": {
"@casl/ability": "^6.7.3",
"@casl/vue": "^2.2.2",
"@directus/sdk": "^19.1.0",
"@floating-ui/dom": "^1.6.13",
"@formkit/drag-and-drop": "^0.4.2",
"@mdi/font": "^7.4.47",
"@nuxthub/core": "^0.8.22",
"@nuxtjs/i18n": "^9.4.0",
"@sindresorhus/is": "^7.0.1",
"@tiptap/extension-highlight": "^2.11.6",
"@tiptap/extension-image": "^2.11.6",
"@tiptap/extension-link": "^2.11.6",
"@tiptap/extension-placeholder": "^2.11.6",
"@tiptap/extension-table": "^2.11.6",
"@tiptap/extension-table-cell": "^2.11.6",
"@tiptap/extension-table-header": "^2.11.6",
"@tiptap/extension-table-row": "^2.11.6",
"@tiptap/extension-text-align": "^2.11.6",
"@tiptap/extension-underline": "^2.11.6",
"@tiptap/pm": "^2.11.6",
"@tiptap/starter-kit": "^2.11.6",
"@tiptap/vue-3": "^2.11.6",
"@vue-pdf-viewer/viewer": "^2.3.1",
"@vueuse/core": "^13.0.0",
"@vueuse/math": "^13.0.0",
"@vueuse/nuxt": "^13.0.0",
"cookie-es": "^2.0.0",
"destr": "^2.0.3",
"echarts": "^5.6.0",
"eslint-plugin-regexp": "^2.7.0",
"jsdom": "^26.0.0",
"jwt-decode": "^4.0.0",
"maska": "^3.1.1",
"next-auth": "4.24.11",
"notivue": "^2.4.5",
"nuxt": "^3.16.1",
"ofetch": "^1.4.1",
"openai": "^4.90.0",
"pinia": "^3.0.1",
"roboto-fontface": "^0.10.0",
"shepherd.js": "^14.5.0",
"swiper": "^11.2.6",
"ufo": "^1.5.4",
"unpdf": "^0.12.1",
"unplugin-vue-define-options": "^3.0.0-beta.7",
"vue-echarts": "^7.0.3",
"vue-flatpickr-component": "^12.0.0",
"vue3-perfect-scrollbar": "^2.0.0",
"vuetify": "^3.7.19",
"webfontloader": "^1.6.28"
},
"devDependencies": {
"@antfu/eslint-config": "^4.11.0",
"@directus/types": "^13.1.0",
"@iconify-json/bx": "^1.2.2",
"@iconify-json/fa": "^1.2.1",
"@iconify-json/mdi": "^1.2.3",
"@iconify-json/tabler": "^1.2.17",
"@iconify/tools": "^4.1.2",
"@iconify/utils": "^2.3.0",
"@iconify/vue": "^4.3.0",
"@intlify/unplugin-vue-i18n": "^6.0.5",
"@nuxtjs/device": "^3.2.4",
"@pinia/nuxt": "^0.10.1",
"@sidebase/nuxt-auth": "^0.10.1",
"@stylistic/stylelint-config": "^2.0.0",
"@stylistic/stylelint-plugin": "^3.1.2",
"@types/jsdom": "^21.1.7",
"@types/node": "^22.13.14",
"@types/webfontloader": "^1.6.38",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"directus-typeforge": "^0.10.2",
"eslint": "^9.23.0",
"eslint-import-resolver-typescript": "^4.3.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-vue": "^10.0.0",
"postcss-html": "^1.8.0",
"postcss-scss": "^4.0.9",
"sass": "^1.86.0",
"stylelint": "^16.17.0",
"stylelint-config-standard-scss": "^14.0.0",
"tsx": "^4.19.3",
"typescript": "^5.8.2",
"vite": "^6.2.3",
"vite-plugin-vuetify": "^2.1.0",
"vite-svg-loader": "^5.1.0"
},
"overrides": {
"postcss": "^8"
},
"resolutions": {
"postcss": "^8"
}
}
Logs
Below is the output from running `bun run build` on my project with Nuxt 3.16.1, Nitro 2.11.7, and `unenv@1.10.0` forced via `resolutions`. The error occurs during the Nitro server build step with the `cloudflare-pages` preset:
bun update v1.2.7 (5c0fa6dc)
$ nuxt prepare && bun run build:icons
✔ Types generated in .nuxt nuxi 8:33:07 PM
$ tsx plugins/iconify/build-icons.ts
Saved CSS to /home/hermes/Projetos-linux/cidadeMobile/plugins/iconify/icons.css!
↑ eslint-import-resolver-typescript 4.2.7 → 4.3.1
+ unenv@1.10.0
ℹ Prerendered 17 routes in 15.808 seconds nitro 8:35:50 PM
✔ Generated public dist nitro 8:35:50 PM
[nitro 8:35:50 PM] ℹ Building Nuxt Nitro server (preset: cloudflare-pages, compatibility date: 2025-03-12)
node_modules/openai/core.mjs (1:30): The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten
node_modules/openai/core.mjs (1:38): The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten
node_modules/openai/core.mjs (7:30): The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten
node_modules/openai/core.mjs (7:38): The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten
[nitro 8:35:52 PM] ERROR Error: ENOTDIR: not a directory, stat '/home/hermes/Projetos-linux/cidadeMobile/node_modules/nitropack/node_modules/unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper'
undefined
[8:35:52 PM] ERROR ENOTDIR: not a directory, stat '/home/hermes/Projetos-linux/cidadeMobile/node_modules/nitropack/node_modules/unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper'
[8:35:52 PM] ERROR ENOTDIR: not a directory, stat '/home/hermes/Projetos-linux/cidadeMobile/node_modules/nitropack/node_modules/unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper'
error: script "build" exited with code 1
This log shows the build failing at the Nitro step, with the `ENOTDIR` error pointing to `unenv/dist/runtime/npm/whatwg-url.mjs/webidl2js-wrapper`. The same error occurs with npm (`npm run build`) and on Cloudflare Pages deployment.