Skip to content

Build1 publisher2 min readPublished

Next.js 16 asks a glibc 2.28 host for GLIBC_2.29 before it reads next.config.ts

A dev.to write-up traces a failed Hostinger deploy of Next.js 16.3.5 to SWC's native bindings. The fix was an .mjs config file and a --webpack flag on the build script, both committed to the repo, with nothing changed on the host.

The Engineer · Build desk

Illustration accompanying Next.js 16 asks a glibc 2.28 host for GLIBC_2.29 before it reads next.config.ts

What happened

  • A Next.js 16.3.5 deploy on Hostinger tried to load @next/swc-linux-x64-gnu and got "/lib64/libm.so.6: version `GLIBC_2.29' not found", then failed to load next.config.ts.
  • The musl variant of the same SWC package was tried next and came back with "/lib64/libc.so: invalid ELF header", so neither native binary loaded.
  • Once the configuration was plain JavaScript, the build got further and stopped again: only WebAssembly bindings were loaded, and Turbopack requires native bindings.
  • The combination that worked was renaming next.config.ts to next.config.mjs and changing the package.json build script from "next build" to "next build --webpack".

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint Writing the config in TypeScript puts the native compiler on the critical path before any application code compiles, so on a host whose glibc predates 2.29 the deploy dies at configuration load.
  • decision A tenant on managed hosting cannot replace the account's glibc, so the choice is between editing the build script and moving hosts.
  • capability A machine with no loadable native SWC binary can still produce a production build, because webpack works with the WASM bindings that Turbopack rejects.
  • cost Everyone on the team who runs npm run build now builds through webpack, and the write-up says nothing about what that did to build time.

Symbol versions are a hard match. An SSH session on the account returned `glibc 2.28` from `getconf GNU_LIBC_VERSION` [4]. The SWC binary wanted the versioned interface named `GLIBC_2.29` out of the math library `libm.so.6` [19]. One minor release apart [1]. SWC is the compiler Next.js uses to transform application code, and its native binaries depend on the operating system they run on [18]. Whether the compiler loads at all is a property of the host. The author notes that neither changing npm dependencies nor picking a newer Node.js version necessarily upgrades the Linux libraries underneath them; replacing glibc by hand in a managed hosting account was not an appropriate fix [20]. The SSH reading does not prove the builder runs the same image, though the build log named the missing interface on the builder itself [5]. Which Node.js patch and npm versions the remote builder used stayed open [21].

A later log message referred to a missing generated configuration module, and Hostinger's automated analysis suggested deleting a corrupted temporary configuration file [16]. According to the write-up, that explanation did not account for the earlier native-library errors, and clearing the Next.js cache would not provide the missing system-library interface [17].

The rename is the smaller change. The `.mjs` extension identifies a JavaScript module Node.js can load without transforming TypeScript syntax, which is what keeps configuration loading clear of the compiler, and Next.js supports the format [6]. The type import came out and the `NextConfig` annotation on `const nextConfig` with it [22]. A JSDoc `@type` comment keeps editor type information [9]. The settings body was preserved, security headers and a conditional Docker output setting included [7], and the application code stayed TypeScript [8].

The second change splits the work between builders. WASM bindings did load, and webpack proceeds with the SWC WASM fallback [11]; the plain script sent the build to Turbopack, which reported that it requires native bindings [4]. The switch is a CLI argument: the write-up records that no `webpack: true` setting, no Next.js downgrade and no manual glibc upgrade were needed [12]. Hostinger's panel stayed as it was, with build command `npm run build`, output directory `.next` and Node.js 22.x [14].

Two conditions have to hold before this transfers to another account. The build log has to name the SWC native load failure, and the refusal has to come from Turbopack itself, since the fallback only works while the WASM bindings still load [10]. The flag also sits in the committed build script, so every `npm run build` follows the host onto webpack, local runs included [3]. I would keep the one script.

What to watch

  • Whether Hostinger moves its build image past glibc 2.28, which would make the --webpack flag unnecessary for this project.
  • Whether Next.js lets a Turbopack build accept WASM bindings, or keeps native bindings as a hard requirement.
  • A second report of the same GLIBC_2.29 symbol error on a different host would show whether the two-line fix generalises beyond one account.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories