Diagnose missing Next package during tools-dev web startup (#675)

* fix(tools-dev): diagnose missing Next package

* fix(web): remove duplicate Ukrainian prompt labels
This commit is contained in:
iulian 2026-05-06 14:45:41 +02:00 committed by GitHub
parent 2455c70d51
commit 80416b185a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 6 deletions

View file

@ -11,13 +11,14 @@ export type StartupLogDiagnostics = {
const NATIVE_ADDON_ABI_MISMATCH_PATTERN = /was compiled against a different Node\.js version[\s\S]*?NODE_MODULE_VERSION\s+\d+[\s\S]*?requires\s+NODE_MODULE_VERSION\s+\d+/i;
const NODE_MODULE_VERSION_PATTERN = /NODE_MODULE_VERSION\s+\d+[\s\S]*?NODE_MODULE_VERSION\s+\d+/i;
const NEXT_PACKAGE_RESOLUTION_PATTERN = /couldn't find the Next\.js package.*from the project directory:/i;
export function detectLogDiagnostics(lines: readonly string[]): LogDiagnostic[] {
const logText = lines.join("\n");
if (!NATIVE_ADDON_ABI_MISMATCH_PATTERN.test(logText) && !NODE_MODULE_VERSION_PATTERN.test(logText)) return [];
const diagnostics: LogDiagnostic[] = [];
return [
{
if (NATIVE_ADDON_ABI_MISMATCH_PATTERN.test(logText) || NODE_MODULE_VERSION_PATTERN.test(logText)) {
diagnostics.push({
message: "Detected a native Node addon ABI mismatch in the daemon log.",
recommendation: [
"Rebuild native daemon dependencies for the active Node version:",
@ -25,8 +26,23 @@ export function detectLogDiagnostics(lines: readonly string[]): LogDiagnostic[]
"or refresh the workspace install:",
" pnpm install",
].join("\n"),
},
];
});
}
if (NEXT_PACKAGE_RESOLUTION_PATTERN.test(logText)) {
diagnostics.push({
message: "Detected that the Next.js package is not resolvable during web startup.",
recommendation: [
"Refresh the workspace install so apps/web/node_modules/next points at the pnpm-managed Next.js package:",
" pnpm install --frozen-lockfile",
"If it still fails, inspect the package link:",
" ls -la apps/web/node_modules/next",
" node -p \"require.resolve('next/package.json', { paths: [process.cwd() + '/apps/web/app'] })\"",
].join("\n"),
});
}
return diagnostics;
}
export function formatLogDiagnostics(diagnostics: readonly LogDiagnostic[]): string | null {

View file

@ -607,8 +607,10 @@ async function startWeb(config: ToolDevConfig, options: CliOptions) {
status,
};
} catch (error) {
const logPath = config.apps.web.latestLogPath;
const lines = await readLogTail(logPath, 80).catch(() => []);
await stopApp(config, APP_KEYS.WEB).catch(() => undefined);
throw error;
throw appendStartupLogDiagnostics(error, APP_KEYS.WEB, createStartupLogDiagnostics(logPath, lines));
}
}

View file

@ -22,6 +22,29 @@ describe("tools-dev diagnostics", () => {
assert.match(diagnostics[0].recommendation, /pnpm install/);
});
it("detects missing Next.js package resolution during web startup", () => {
const diagnostics = detectLogDiagnostics([
"Turbopack build failed with 1 errors:",
"./apps/web/app",
"Error: Next.js inferred your workspace root, but it may not be correct.",
"We couldn't find the Next.js package (next/package.json) from the project directory: /repo/apps/web/app",
]);
assert.equal(diagnostics.length, 1);
assert.match(diagnostics[0].message, /Next\.js package is not resolvable/);
assert.match(diagnostics[0].recommendation, /apps\/web\/node_modules\/next/);
assert.match(diagnostics[0].recommendation, /pnpm install --frozen-lockfile/);
});
it("detects missing Next.js package resolution when details change", () => {
const diagnostics = detectLogDiagnostics([
"Error: We couldn't find the Next.js package from the project directory: /repo/apps/web/app",
]);
assert.equal(diagnostics.length, 1);
assert.match(diagnostics[0].message, /Next\.js package is not resolvable/);
});
it("does not report diagnostics for unrelated logs", () => {
assert.deepEqual(detectLogDiagnostics(["daemon booting", "ready"]), []);
});