Summary
A Next.js application that runs flawlessly on a developer machine but suddenly fails on a server with “unexpected end of input” almost always indicates a runtime-level corruption of the JavaScript bundle, not an application‑level bug. In this case, the failure appeared after a hacking incident and persisted across Docker, systemd, and even a fresh VPS — a strong signal that the build artifacts or the environment producing them are being altered, truncated, or blocked.
Root Cause
The most common root causes for this exact failure pattern are:
- Corrupted or partially served JavaScript bundles (e.g.,
.next/server/app/*.jsor.next/static/chunks/*.js) - Reverse proxy truncation (Nginx, Caddy, Traefik cutting responses mid‑stream)
- Filesystem corruption after an attack or abrupt shutdown
- Node.js version mismatch between local and server
- Build-time environment differences causing Next.js to emit incompatible output
- Malicious or broken caching layers returning incomplete JS files
- Security software or malware altering files after build
The key takeaway: Next.js is not failing — the server is delivering incomplete JavaScript.
Why This Happens in Real Systems
Real production systems fail this way because:
- JS bundlers assume the filesystem is reliable; any truncation produces invalid syntax.
- Reverse proxies silently truncate responses when hitting size/time limits.
- Compromised servers often have lingering rootkits that modify or delete files.
- Docker hides underlying host issues, so when Docker and systemd both fail, the host is the problem.
- Next.js builds are large, making them more vulnerable to partial writes or corrupted caches.
Real-World Impact
When this failure occurs:
- All Next.js routes fail, even static ones.
- SSR crashes immediately because the server cannot parse the corrupted bundle.
- Client-side hydration breaks, causing blank pages.
- Re-deployments do nothing, because the environment keeps corrupting the output.
This is why the user saw the same error even on a new VPS — the build machine or deployment pipeline is likely producing corrupted artifacts.
Example or Code (if necessary and relevant)
Below is an example of what a truncated bundle looks like when served:
export function handler() {
return fetch("/api/data").then(res => res.json())
This file ends abruptly — exactly what triggers “unexpected end of input”.
How Senior Engineers Fix It
Senior engineers approach this systematically:
1. Verify the bundle integrity
- Compare file sizes between local
.nextand server.next - Use checksums (e.g.,
sha256sum) to confirm files are identical
2. Rebuild on the server
- Build directly on the VPS to eliminate CI/CD corruption
- Ensure Node.js versions match (
node -v)
3. Check reverse proxy limits
- Increase Nginx/Caddy/Traefik:
client_max_body_sizeproxy_buffer_sizeproxy_busy_buffers_size
4. Disable all caching layers
- CDN
- Reverse proxy caching
- Docker layer caching
5. Scan for rootkits or tampering
- Use tools like:
rkhunterchkrootkitclamav
6. Rebuild the server from a clean image
If the system was hacked, senior engineers never trust the machine again.
7. Recreate the build pipeline
If even a new VPS fails, the machine doing the build is likely compromised or misconfigured.
Why Juniors Miss It
Juniors often misdiagnose this issue because:
- They assume Next.js is broken, not the server.
- They don’t check file integrity or response truncation.
- They trust that a “fresh VPS” means a clean environment.
- They overlook Node.js version mismatches.
- They don’t suspect CI/CD corruption or malware.
- They focus on the error message instead of the delivery path of the JS bundle.
A senior engineer recognizes that syntax errors in production but not in development almost always mean the file was altered, truncated, or served incorrectly.
If you want, I can walk you through a step‑by‑step diagnostic checklist tailored to your exact deployment setup.