feat(dev): explain first-run failures before nuxt loads - #1444
Conversation
commit: |
📝 WalkthroughWalkthroughThe Nuxt CLI now runs project preflight checks before starting the development server. The checks locate current or ancestor projects, validate writable directories, verify Nuxt dependencies, detect package managers, and handle missing installations. The dev command updates raw Estimated code review effort: 4 (Complex) | ~45 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/nuxt-cli/src/dev/preflight.ts`:
- Around line 178-190: Update checkWritableBuildDir to stat an existing .nuxt
path, require it to be a directory, and validate both write and traversal
permissions with W_OK | X_OK; treat a non-directory target as invalid so it must
be removed. Update the recovery message and corresponding unit test to use chmod
u+wx.
- Around line 193-209: Update checkDependencies so an undefined result from
readPackageJson(cwd) throws an ActionableError instructing the user to create or
repair package.json before adding Nuxt, instead of calling offerInstall. Add
regression tests covering missing and malformed package.json files alongside a
valid nuxt.config, while preserving the existing behavior for valid manifests.
🪄 Autofix
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 Plus
Run ID: bc333821-6c0f-415b-970b-bed765a2e380
📒 Files selected for processing (11)
packages/nuxt-cli/src/commands/dev.tspackages/nuxt-cli/src/commands/module/add.tspackages/nuxt-cli/src/dev/preflight.tspackages/nuxt-cli/src/utils/args.tspackages/nuxt-cli/src/utils/console.tspackages/nuxt-cli/src/utils/errors.tspackages/nuxt-cli/src/utils/install.tspackages/nuxt-cli/src/utils/nuxt-config.tspackages/nuxt-cli/test/unit/errors.spec.tspackages/nuxt-cli/test/unit/preflight.spec.tspackages/nuxt-cli/test/unit/utils/args.spec.ts
| function checkWritableBuildDir(cwd: string): void { | ||
| const buildDir = join(cwd, '.nuxt') | ||
| const target = existsSync(buildDir) ? buildDir : cwd | ||
| try { | ||
| accessSync(target, constants.W_OK) | ||
| } | ||
| catch { | ||
| throw new ActionableError([ | ||
| `${styleText('red', 'Nuxt cannot write to')} ${styleText('cyan', target)}${styleText('red', '.')}`, | ||
| '', | ||
| `Grant write access with ${styleText('cyan', `chmod u+w ${relativeTo(cwd, target, { link: false })}`)}, or remove the directory and try again.`, | ||
| ].join('\n')) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
file="packages/nuxt-cli/src/dev/preflight.ts"
printf '%s\n' '--- imports and target function ---'
rg -n -A35 -B12 'function checkWritableBuildDir|from .node:fs' "$file"
printf '%s\n' '--- call sites ---'
rg -n -C3 'checkWritableBuildDir' packages/nuxt-cliRepository: nuxt/cli
Length of output: 4852
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- related tests and documentation ---'
rg -n -i -C3 'checkWritableBuildDir|cannot write to|\.nuxt.*write|W_OK|X_OK' \
packages/nuxt-cli test tests packages 2>/dev/null || true
printf '%s\n' '--- Node fs constants and local runtime availability ---'
node - <<'JS'
const { constants } = require('node:fs')
console.log(JSON.stringify({ W_OK: constants.W_OK, X_OK: constants.X_OK, W_OR_X: constants.W_OK | constants.X_OK }))
JS
printf '%s\n' '--- POSIX permission model for representative paths ---'
python3 - <<'PY'
import stat
cases = {
"directory_writable_only": 0o600,
"directory_writable_searchable": 0o700,
"regular_file_writable_only": 0o600,
"regular_file_writable_executable": 0o700,
}
for name, mode in cases.items():
print(name, oct(mode),
"owner_write=", bool(mode & stat.S_IWUSR),
"owner_execute_or_search=", bool(mode & stat.S_IXUSR))
PYRepository: nuxt/cli
Length of output: 6245
🏁 Script executed:
#!/bin/bash
set -eu
cat -n packages/nuxt-cli/test/unit/preflight.spec.ts | sed -n '105,160p'
cat -n packages/nuxt-cli/src/dev/preflight.ts | sed -n '100,215p'Repository: nuxt/cli
Length of output: 7732
Check .nuxt type and traversal permission.
accessSync(target, constants.W_OK) accepts a writable regular file and does not check directory search permission. Validate an existing .nuxt with statSync(...).isDirectory() and check constants.W_OK | constants.X_OK. Update the recovery command and unit test to use chmod u+wx; a non-directory path must be removed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/nuxt-cli/src/dev/preflight.ts` around lines 178 - 190, Update
checkWritableBuildDir to stat an existing .nuxt path, require it to be a
directory, and validate both write and traversal permissions with W_OK | X_OK;
treat a non-directory target as invalid so it must be removed. Update the
recovery message and corresponding unit test to use chmod u+wx.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/nuxt-cli/test/unit/preflight.spec.ts (1)
147-155: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the remediation command for a non-searchable directory.
The matcher at Line [155] checks only
Nuxt cannot write to. It can pass if the error loses the actionablechmod u+wx .nuxtcommand.Proposed test assertion
- await expect(preflight({ cwd: tempDir, interactive: false })).rejects.toThrow(/Nuxt cannot write to/) + await expect(preflight({ cwd: tempDir, interactive: false })).rejects.toThrow(/Nuxt cannot write to[\s\S]*chmod u\+wx \.nuxt/)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/nuxt-cli/test/unit/preflight.spec.ts` around lines 147 - 155, Update the preflight test case around the skipped “should explain a build directory that cannot be searched” test to assert that the rejection message includes both “Nuxt cannot write to” and the actionable “chmod u+wx .nuxt” remediation command. Preserve the existing permission setup and platform skip conditions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/nuxt-cli/test/unit/preflight.spec.ts`:
- Around line 147-155: Update the preflight test case around the skipped “should
explain a build directory that cannot be searched” test to assert that the
rejection message includes both “Nuxt cannot write to” and the actionable “chmod
u+wx .nuxt” remediation command. Preserve the existing permission setup and
platform skip conditions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d2861d58-45bc-4d12-9a87-cf92bc10cb6e
📒 Files selected for processing (2)
packages/nuxt-cli/src/dev/preflight.tspackages/nuxt-cli/test/unit/preflight.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/nuxt-cli/src/dev/preflight.ts
🔗 Linked issue
📚 Description
running
nuxt devone directory too deep, or before installing, currently fails somewhere deep inside@nuxt/kitwith a stack trace and advice to installnuxt(which is already installed, one directory up).this adds a preflight stage in
dev/preflight.tsthat runs before any Nuxt code loads, asking:nuxtresolvableeach problem is either offered a fix or reported as an
ActionableError, whose message carries the command to run and whose stack is suppressed so the terminal shows advice rather than frames insidedist.when
nuxt devwas launched in a subdirectory of the actual nuxt project, then rather than just failing, as we did before, we offer the project above: