kit icon indicating copy to clipboard operation
kit copied to clipboard

`vite build` fails with ENAMETOOLONG

Open iva2k opened this issue 2 years ago • 4 comments

Describe the bug

Build vite build of demo app (npm create svelte@latest) fails with ENAMETOOLONG in src/exports/vite/index.js L460 in 'Prerendering' phase when it tries to fork().

https://github.com/sveltejs/kit/blob/96751b0636f1cd511498de1de4d70990079348ea/packages/kit/src/exports/vite/index.js#L460

Root cause is L467 packing env.private and env.public and overflowing 32kB.

https://github.com/sveltejs/kit/blob/96751b0636f1cd511498de1de4d70990079348ea/packages/kit/src/exports/vite/index.js#L467

If env.private is large (e.g. due to a bunch of "npm_*" variables added by pnpm (or is it vite that adds all of them?), e.g. contains a bunch of 'npm_package_devDependencies' and other internal npm stuff), it is passed to fork(script, ...) as args, and it cannot handle such a large environment (more than 32kB size).

Reproduction

npm create svelte@latest repro
# choose "demo app"
cd repro
pnpm i
pnpm build

it typically works.

Now need a large environment, which is quite common on Windows (with long PATH and many software-specific variables added), and compounded by pnpm which adds a crapload of "npm_*" variables for each package.json script, dependency and devDependency...

Do this:

source craploadEnv.sh
pnpm build

And get "ENAMETOOLONG"

where craploadEnv.sh is:

export CRAP_ENV_1="very long string"
export CRAP_ENV_2="very long string"
... 
# Iterate a thousand times

Logs

No response

System Info

Windows 10 64 bits
@sveltejs/kit@next

Severity

blocking all usage of SvelteKit

Additional Information

I made a hotfix pnpm patch that prunes env.private from all "npm_*" variables and it fixes the error. Uncomment one of the console.log() lines to see the content and size of env.private, when it reaches 32kB, bad things happen.

diff --git a/src/exports/vite/index.js b/src/exports/vite/index.js
index 179104d8c19b44b432f414f61ed506beb8d65faa..37249d2e3342e367e6c0d0347406f3f0bca4fe6d 100644
--- a/src/exports/vite/index.js
+++ b/src/exports/vite/index.js
@@ -449,6 +449,14 @@ function kit() {
 						new URL('../../core/prerender/prerender.js', import.meta.url)
 					);
 
+					// [iva2k] pnpm adds a ton of environmental variables "npm_..." and fork() chokes with "spawn ENAMETOOLONG" error.
+					// Removing all "npm_*" variables solves the issue:
+					const env_filtered = Object.keys(env.private).filter(key => !/^npm_/.test(key)).reduce((acc, key) => {
+					  acc[key] = env.private[key];
+					  return acc;
+					}, { });
+					// console.log('DEBUG [spawn ENAMETOOLONG error] len(env.private+public)=%o, len(filtered)=%o, filtered=%o', JSON.stringify({ ...env.private, ...env.public }).length, JSON.stringify({ ...env_filtered, ...env.public }).length, env_filtered);
+					// console.log('DEBUG [spawn ENAMETOOLONG error] len(env.private+public)=%o, len(filtered)=%o', JSON.stringify({ ...env.private, ...env.public }).length, JSON.stringify({ ...env_filtered, ...env.public }).length);
 					const child = fork(
 						script,
 						[
@@ -456,7 +464,8 @@ function kit() {
 							manifest_path,
 							results_path,
 							'' + verbose,
-							JSON.stringify({ ...env.private, ...env.public })
+							// JSON.stringify({ ...env.private, ...env.public })
+							JSON.stringify({ ...env_filtered, ...env.public })
 						],
 						{
 							stdio: 'inherit'

iva2k avatar Dec 11 '22 23:12 iva2k

It can also be just code 4294967295 in Windows 10 or code 255 in github actions (linux).

AlexRMU avatar Dec 22 '22 15:12 AlexRMU

A simple temporary solution:

//vite.config.ts
process.env = Object.fromEntries(Object.entries(process.env).filter(x => x[0].startsWith("NODE"))); //or something similar

AlexRMU avatar Dec 23 '22 12:12 AlexRMU

But I keep getting this error, which differs at least in the error code. Perhaps https://github.com/sveltejs/kit/issues/8246 is not a duplicate?

AlexRMU avatar Dec 23 '22 12:12 AlexRMU

@AlexRMU Thanks for the suggestion - though instead of passing "NODE*" ones, I removed "npm_*" ones (that seem to be coming from pnpm), that also preserves build-time environment variables like secrets etc.

// vite.config.ts
process.env = Object.fromEntries(
  Object.entries(process.env).filter((x) => !x[0].startsWith('npm_'))
);

It is a better workaround than patching @svelte/kit package code.

iva2k avatar Dec 28 '22 02:12 iva2k