vercel/next.js · error

Node.js version parse error

Error message

Node.js version parse error

What it means

Thrown by EdgeWorkerEnvironment::runtime_versions() when the resolved Node.js version string cannot be parsed into a semver Version via preset_env_base::Version::from_str. The version string originates either from shelling out to `node --version` (stripped of its leading 'v') or from a statically configured NodeJsVersion value. Parsing fails when the string is not a plain numeric semver like "20.11.0".

Source

Thrown at turbopack/crates/turbopack-core/src/environment.rs:356

    // This isn't actually the Edge's worker environment, but we have to use some kind of version
    // for transpiling ECMAScript features. No tool supports Edge Workers as a separate
    // environment.
    pub node_version: ResolvedVc<NodeJsVersion>,
}

#[turbo_tasks::value_impl]
impl EdgeWorkerEnvironment {
    #[turbo_tasks::function]
    pub async fn runtime_versions(&self) -> Result<Vc<RuntimeVersions>> {
        let str = match *self.node_version.await? {
            NodeJsVersion::Current(process_env) => get_current_nodejs_version(*process_env),
            NodeJsVersion::Static(version) => *version,
        }
        .await?;

        Ok(Vc::cell(Versions {
            node: Some(
                Version::from_str(&str).map_err(|_| anyhow!("Node.js version parse error"))?,
            ),
            ..Default::default()
        }))
    }
}

// TODO preset_env_base::Version implements Serialize/Deserialize incorrectly
#[derive(Debug)]
#[turbo_tasks::value(transparent, serialization = "skip")]
pub struct RuntimeVersions(#[turbo_tasks(trace_ignore)] pub Versions);

#[turbo_tasks::value_impl]
impl RuntimeVersions {
    /// Whether the environment supports arrow functions.
    #[turbo_tasks::function]
    pub fn supports_arrow_functions(&self) -> Vc<bool> {
        // https://github.com/babel/babel/blob/b0e3517dc566880e76b5f1f4dcf7fcecba58337d/packages/babel-compat-data/data/plugins.json#L363-L376
        // "chrome": "47",

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Use a plain semver string (major.minor.patch, e.g. "20.11.0") for any statically configured NodeJsVersion.
  2. Run `node --version` in the project shell and confirm it prints a standard `vX.Y.Z`; fix or replace the broken Node binary if not.
  3. If you derive the version programmatically, strip all non-numeric/channel suffixes before passing it to the environment.
  4. Check that no wrapper script or version manager (nvm/fnm) is injecting non-semver output into `node --version`.

Example fix

// before
NodeJsVersion::Static(ResolvedVc::cell(rcstr!("lts/hydrogen")))

// after
NodeJsVersion::Static(ResolvedVc::cell(rcstr!("20.11.0")))
Defensive patterns

Strategy: validation

Validate before calling

// Validate a version string is plain semver before passing it as a static NodeJsVersion.
fn is_plain_semver(s: &str) -> bool {
    let mut parts = s.split('.');
    parts.clone().take(3).all(|p| p.parse::<u64>().is_ok())
        && parts.next().is_none() // exactly major.minor.patch
}

// usage
let v = "20.11.0";
assert!(is_plain_semver(v), "node version must be plain semver");

Prevention

When it happens

Trigger: Constructing an EdgeWorkerEnvironment whose node_version resolves to a non-semver string (e.g. a literal like "lts/hydrogen", "current", an empty string, or text with unexpected suffixes). Also fires when `node --version` emits output that, after stripping 'v', isn't valid semver.

Common situations: Passing a custom environment-version string that carries a distribution label or channel suffix; an unusual/corrupted Node.js installation whose --version prints non-semver text; misconfiguration of a static node version in Turbopack environment wiring.

Understand the failure class

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/bf0a60bc924634b0. Report an issue: GitHub.