• Latest
  • Trending
  • All

Developer Error Fix Hub: EACCES, ENOENT, CORS, 502 and More 2026

June 10, 2026
ssh command cheatsheet

SSH Command Cheatsheet: Connect, Keys, scp, Tunnels (2026)

June 16, 2026
chmod-chown-cheatsheet

chmod and chown Cheatsheet: Linux Permissions, Decoded (2026)

June 16, 2026
systemctl-journalctl-cheatsheet

systemctl + journalctl Cheatsheet: Services and Logs (2026)

June 16, 2026
grep-cheatsheet

The grep Cheatsheet: Search a File, Search a Tree (2026)

June 16, 2026
rsync-cheatsheet

The rsync Cheatsheet: Mirror, Sync, Copy Over SSH (2026)

June 16, 2026
curl-cheatsheet

curl Cheatsheet: Download Files and Test APIs (2026)

June 16, 2026
iptables-vs-nftables-cheatsheet cheatsheet

iptables vs nftables: Linux Firewall Cheatsheet, Side by Side

June 16, 2026
nmcli-cheatsheet cheatsheet

nmcli Cheatsheet: Wi-Fi and Network Connections From the Linux Terminal

June 16, 2026
powershell-networking-cheatsheet cheatsheet

PowerShell Networking Cheatsheet: Test-NetConnection, IP, DNS (2026)

June 16, 2026
tar command cheatsheet

The tar Command Cheatsheet: Create, Extract, Stop Guessing (2026)

June 16, 2026
Linux find command cheatsheet

The find Command Cheatsheet: Every Recipe You Actually Use (2026)

June 15, 2026
Linux networking commands cheatsheet, ip and ss

Linux Networking Commands in 2026: the ip and ss Cheatsheet

June 15, 2026
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools
Tuesday, June 16, 2026
  • Login
People Are Geek
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools
No Result
View All Result
People Are Geek
No Result
View All Result
Home Developer Tools

Developer Error Fix Hub: EACCES, ENOENT, CORS, 502 and More 2026

by People Are Geek
June 10, 2026
in Developer Tools
0
0
SHARES
9
VIEWS
Share on FacebookShare on Twitter

Developer error encyclopedia

These are the errors I keep hitting. So I wrote down how I actually fix them. For each one you get the exact thing the terminal or browser spits at you, then why it’s really happening (the surface story usually lies), then the steps I run to make it go away. All of it checked against current tooling, not some answer that’s been rotting since 2019. Eight so far. Node.js, Python, npm, the browser, a couple of reverse-proxy headaches. Paste your error in the search box, or tap a filter chip, and it jumps you to whichever one matches your stack.

Everything’s open by default. Start typing. The matches stay, the rest vanish.

Entries8
Technologies coveredNode.js · Python · npm · Browser · Nginx
UpdatedMay 2026
Page sourceFree, no signup

EACCES: permission denied

node.jslinuxfilesystem

What you see

Error: EACCES: permission denied, open '/etc/myapp/config.json'
    at Object.openSync (node:fs:603:3)
    at Object.readFileSync (node:fs:471:35)

Why it happens

Your Node process reached for a path the OS won’t let it touch. Almost always it’s one of two things. Either the file belongs to somebody else (root, usually) while your process runs as a different user. Or the permission bits just lock you out, picture mode 600 owned by root. That’s the whole story most days.

Fix

  1. Grab the path that’s failing. The error hands it to you (/etc/myapp/config.json in this case).
  2. See who owns it and what the bits are with ls -la /etc/myapp/config.json. First column is the bits. Third is the owner. That’s all you’re reading here.
  3. Fix the bits if you’re meant to have access anyway. Give the owner read with chmod u+r /etc/myapp/config.json, or just open it up with chmod 644.
  4. Fix the ownership when the file landed under the wrong account: sudo chown $USER:$USER /etc/myapp/config.json.
  5. Stop reaching for sudo on reflex. Most of the time this is nothing but a Node app trying to write into a folder some other user created. Put the writable folder somewhere in the user’s home, leave it there. And please, don’t chmod 777 a system path just to make the pain stop. I’ve watched that decision come back to bite people.
  6. If it’s an npm global install: EACCES on /usr/lib/node_modules means point npm at a folder under ~/.npm-global rather than running sudo npm install -g. Drop ~/.npm-global/bin on your PATH and you’re set. No root, ever again.

ENOENT: no such file or directory

node.jsfilesystem

What you see

Error: ENOENT: no such file or directory, open './config/local.json'
    at Object.openSync (node:fs:603:3)

Why it happens

The path you handed Node doesn’t point at a real file. What gets me most often? A relative path that quietly leans on the current working directory, which is never the same under a systemd service as it was on my laptop. After that it’s the boring stuff. A typo in the filename, a file that never made it into the deploy bundle. Or a symlink dangling off into nowhere.

Fix

  1. Print the path Node actually resolved right before the call that blows up: console.log(require('path').resolve('./config/local.json')). Then go check where the file really sits. Nine times out of ten they don’t match, and there’s your bug.
  2. Go absolute with path.join(__dirname, 'config', 'local.json'). __dirname is the folder of the source file itself, so it couldn’t care less what the runtime cwd happens to be. This is the fix I lean on, probably too much.
  3. If it only breaks on the server run ls -la in the systemd service’s working directory and see if the file is even there. More often than you’d think, the build pipeline just left it behind.
  4. When the file is genuinely allowed to be missing wrap the read in try/catch and fall back to a default, or check fs.existsSync() first instead of letting it throw.
  5. Watch for stray whitespace in paths you build at runtime. A filename pulled from a CSV loves to drag along a trailing space or a newline. Trim it before it ever reaches the fs call. Skip that and you’ll lose an hour glaring at two strings that look identical.

EADDRINUSE: address already in use

node.jsnetworkport

What you see

Error: listen EADDRINUSE: address already in use :::3000
    at Server.setupListenHandle [as _listen2] (node:net:1740:16)

Why it happens

Something else is already parked on the port you wanted. Usually it’s a previous run of your own app that didn’t die cleanly. Sometimes it’s a totally different service squatting there (a Docker container, or some other framework’s dev server you forgot was running). Or a zombie nodemon left breathing after a hot reload. Whatever it is, the port’s taken, and the kernel won’t hand the same one out twice.

Fix

  1. Find out who’s holding it. On Linux/macOS I run lsof -iTCP:3000 -sTCP:LISTEN -n -P. On Windows it’s netstat -ano | findstr :3000, and then you chase down the PID it prints.
  2. Kill the squatter: kill -9 <PID> on Linux/macOS, or taskkill /F /PID <PID> on Windows.
  3. Or just move. When 3000 is forever contested, this is the quickest unblock in dev: PORT=3001 node server.js. Get on with your day.
  4. Reuse the socket on startup if leftover sockets after a crash are your real problem. Plenty of frameworks expose a reusePort or exclusive option (SO_REUSEADDR under the hood) for precisely this.
  5. Sometimes you just wait. After a crash the kernel can park a TCP socket in TIME_WAIT for up to two minutes. Nothing’s broken. It just hasn’t let go yet. If you can pick the port at startup, bind to 0.0.0.0:0 and take whatever free one it gives you. Otherwise, go grab a coffee.

CORS error: blocked by Access-Control-Allow-Origin

browserapinetwork

What you see

Access to fetch at 'https://api.example.com/users'
from origin 'https://app.example.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

Why it happens

Here’s the part that trips everyone up. Your request probably worked fine. The browser just refused to hand the cross-origin response back to your page, because the server never sent an Access-Control-Allow-Origin header matching where the page came from. CORS lives in the browser, not the server. So the API got your call, built a perfectly good response, and the browser dropped it on the floor before a single line of your JavaScript ever laid eyes on it.

Fix

  1. Prove it from the server side first by curling the API yourself: curl -i -H "Origin: https://app.example.com" https://api.example.com/users. No Access-Control-Allow-Origin header in the response? There’s your answer.
  2. Fix it at the server when it’s yours. Send the header back for the right origin, and drop * the moment credentials are in play. Express: app.use(cors({ origin: 'https://app.example.com', credentials: true })). Nginx: add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always;.
  3. Don’t forget the preflight on anything that isn’t a simple request. The browser fires an OPTIONS first, and it has to come back carrying Access-Control-Allow-Methods and Access-Control-Allow-Headers. A 404 on that OPTIONS call surfaces as the exact same CORS error, which is maddening right up until the second you spot it.
  4. Can’t touch the API? Proxy around it. Serve /api/* from the same origin as your app and let nginx proxy_pass through to the real host. Now the browser thinks the whole thing is same-origin, and CORS never enters the conversation. It’s how I handle third-party APIs I don’t own.
  5. Whatever you do, don’t launch the browser with web security switched off, and don’t slap Access-Control-Allow-Origin: * on a response that’s carrying credentials. Both of those “work,” and both are how you quietly ship a security hole to production.

502 Bad Gateway

nginxproxy5xx

What you see

Could be a bare Nginx page reading “502 Bad Gateway”. Could be one of Cloudflare’s branded 502 screens. Could be a plain HTTP 502 landing on a fetch in your console. Same problem, different clothes.

Why it happens

A 502 means the proxy parked in front of your app (Nginx, Apache, Cloudflare, an ELB, take your pick) either got garbage back from the upstream or got nothing at all. The list of usual suspects is short. Your app crashed and the socket’s closed. Or your app’s alive but slow, and the proxy gave up waiting. Or the two are talking straight past each other, the proxy speaking HTTP/1.1 at a process that only answers in HTTP/2 cleartext. The proxy itself is rarely the villain here. It’s just the one carrying the bad news.

Fix

  1. First, is the upstream even up? From the proxy box itself, curl -i http://127.0.0.1:8080/health. If that fails right there, stop staring at Nginx. The bug’s in your app.
  2. Read the proxy’s error log. Nginx drops it in /var/log/nginx/error.log, and the line tells you flat-out what went wrong: connection refused, a timeout, upstream closed prematurely. Second place I always look.
  3. Bump the timeout when the upstream works but takes its sweet time: proxy_read_timeout 60s; in Nginx, or the Apache equivalent.
  4. Get the protocols on the same page. If the upstream is HTTP/2, either make the proxy talk HTTP/2 to it, or keep the upstream serving HTTP/1.1 too. Classic trap here: Cloudflare’s “Always Use HTTPS” pointed at a plain-HTTP origin spins up a neat little 502 loop.
  5. Hunt the restart loop. When a systemd unit keeps falling over, systemctl status shows the restart count climbing. A service that dies every few seconds throws 502s that flicker in and out and slowly drive you up the wall. Fix the crash. Not the proxy.

ModuleNotFoundError: No module named ‘X’

pythonpipvenv

What you see

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

Why it happens

Python walked its import path and the module simply wasn’t on it. The one that bites me constantly? I install the package in one place and run Python from another. Pip drops it in the global site-packages while my code runs inside a venv, or the reverse. Then there’s two Python versions on the same box reading from different site-packages, or the occasional typo in the module name. And the circular import where a module reaches for itself before it’s done loading. That covers nearly every case I’ve ever hit.

Fix

  1. Pin down which Python you’re actually running: python --version plus which python (where python on Windows). It has to be the interpreter inside your venv. If it isn’t, well, you’ve already found the problem.
  2. Activate the venv before you install or run anything: source venv/bin/activate on Linux/macOS, venv\Scripts\activate on Windows.
  3. Install into that exact interpreter with python -m pip install requests. I always reach for the python -m pip form. It guarantees pip lands the package in the same Python you’re about to run, and there’s no guessing involved.
  4. Make sure it took: python -c "import requests; print(requests.__file__)". The path it prints tells you exactly which site-packages the module came from.
  5. Double-check the name, because install name and import name don’t always line up. pillow imports as PIL. beautifulsoup4 as bs4. opencv-python as cv2. That mismatch has cost me more hours than I’d care to admit out loud.

SyntaxError: Unexpected token < in JSON at position 0

javascriptjsonapi

What you see

Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "...
is not valid JSON

Why it happens

You called JSON.parse on something that isn’t JSON. That leading < (usually a full <!DOCTYPE html>) gives it away: the server sent back HTML while your code sat there expecting JSON. What’s really going on, almost every single time, is a 4xx or 5xx underneath. The API hit an error, handed back its branded HTML error page, and your code cheerfully called .json() on it without so much as glancing at the status code. The parser throws. But the parser isn’t your bug.

Fix

  1. Actually look at what came back before you parse it. Open the Network tab, find the failing request, read the response body. If it’s HTML? Congratulations, the server returned an error and you just found it in ten seconds.
  2. Gate on the status code before .json() ever runs: if (!response.ok) throw new Error(`HTTP ${response.status}`). This one line would have headed off most of the cases I’ve seen.
  3. Trust the Content-Type. Only reach for .json() when it starts with application/json. Otherwise grab response.text() and throw something a human can actually read.
  4. Recheck the URL. A 404 on a wrong path will often serve your SPA’s index.html instead of the API JSON, which is exactly why the body reads like a webpage. Confirm in the Network tab that the URL matches what the API really exposes.
  5. Suspect an auth redirect. An expired session loves to answer a JSON fetch with a login page in HTML. Catch the 401, or the redirect chain, and handle it before you hand anything off to the parser.

npm ERR! ERESOLVE could not resolve / peer dep missing

npmnode.jsdependency

What you see

npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR! While resolving: my-app@1.0.0
npm ERR! Found: react@18.2.0
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^17.0.0" from some-legacy-lib@2.3.4

Why it happens

Since npm 7 the resolver actually enforces peer dependencies instead of shrugging them off. It spots a package insisting on React 17 while you’re shipping React 18, decides the two can’t share a roof, and bails rather than install a tree it reckons is broken. The real reason underneath is usually pretty mundane. A dependency that’s gone stale. A typo in some version range in your package.json. Or two transitive deps that flat-out disagree about which peer they want.

Fix

  1. Name the troublemaker. The error literally tells you which package (some-legacy-lib@2.3.4) and what it’s fighting over. Go check whether the registry has a newer version that’s made its peace with your React.
  2. Bump it: npm install some-legacy-lib@latest. Most maintenance releases have already caught up to the current major of React, so this often just ends the whole thing right there.
  3. If the package is dead, walk away from it. A maintained fork, or a different library doing the same job, beats wrestling something nobody’s touched in two years.
  4. Force it only when you’ve earned the right: npm install --legacy-peer-deps skips the check entirely. I reach for this rarely. Only when I’m dead certain the peer warning is just wrong, and even then I leave a note in the README saying why, so future-me doesn’t sit there panicking.
  5. Don’t trust an old lockfile. A stale package-lock.json can pin a transitive that stopped being compatible ages back. rm package-lock.json node_modules && npm install rebuilds the whole thing clean, and honestly that alone clears it more often than it has any right to.
No entry matches your search. Try a broader term or clear the filter chips.

Why a curated dev error hub is more useful than 100 random Stack Overflow tabs

Don’t get me wrong. Stack Overflow is brilliant when your question is genuinely new. But mid-outage it turns into a tax. You read an accepted answer from 2014, then two upvoted ones from 2019, then a comment thread that trails off into “fixed by upgrading the library, not sure which version.” A focused hub makes the opposite bet. One error per entry, the cause stated up top before anything else, the fix as a short numbered list, every snippet run against what people actually use today (Node 22+, Python 3.12+, npm 10+, current browsers). When you’re stuck and you need out in two minutes, that’s the trade I’ll take.

I’m starting with eight, picked by how often people search them and how badly they sting on impact. More are coming down the long tail. Transport errors like EHOSTUNREACH and ECONNREFUSED. The language-specific stuff (Go panics, the Rust borrow checker, Java’s NullPointerException). And the platform headaches, Docker exit codes, Kubernetes CrashLoopBackOff. The shape won’t budge, though. One error per entry, four blocks, what you see plus why plus fix plus related. Straight to the point, no clickbait.

How to use this page during a debugging session

  1. Grab the error code, or the first few words of the stack trace, and paste it in the search box. Matches stay. Everything else hides. I kept the matching loose on purpose, it reads the visible text and the tags both, so a partial code, a lowercase fragment, or just the symptom (“permission denied”) will each land you somewhere useful.
  2. Filter by stack when you already know your context: Node.js, Python, Browser, Nginx, filesystem, network, process. It’s loose here too. A Node.js entry still turns up under “filesystem” if it carries that tag as well. Hit “All” to drop the filter again.
  3. Read “Why it happens” before you touch the fix. I’m guilty of skipping straight to the commands, and it bites every time. You get a green build with the real bug still lurking underneath, and a week later the same error crawls back wearing a slightly different face and eats another afternoon. Read the why.
  4. Bookmark the deep link. Every error has its own anchor (#eacces, #cors, and so on). Send the anchored URL to a teammate and they’re staring at the same thing in two seconds. Or pin it in Slack, so the next person who hits it lands on a real answer instead of opening a fresh Google spiral.

Conventions used in every entry

Every entry here is built the same way on purpose, so you can scan a long page fast and always know where to look. What you see is the raw text or stack trace the runtime actually prints, copied word for word, partly so that when you land here off a search it lines up with what’s already on your screen. Why it happens is one paragraph chasing the cause behind the cause: not “this happens when X,” but “X happens because Y, and Y is usually something Z in your own project quietly set off.” How to fix is a numbered list of real commands and code changes, ordered cheap to deep. Flip a flag or set an env var first. Refactor or bump a major version only if you genuinely have to. And Related points you at other entries or tools on PeopleAreGeek that tend to show up in the same mess. The HTTP 502 entry, for one, links the CDN detector and the HTTP headers checker, because you usually need both of them to reproduce the thing. Every snippet runs against the current generation of whatever runtime the entry names, and when a major version ships I go in and swap the examples. I’d rather do that than leave a stale answer quietly sitting on the page.

What this hub will become (roadmap)

Eight is just where this starts. Over the next quarter I want to grow it into a proper database of 100 to 200 entries in this same format, then spin each one out as its own page so it can rank on its specific long-tail search (“EACCES Node.js fix”, “ENOENT no such file or directory”, that kind of thing). Each of those keeps the four blocks, adds a real reproduction you can run yourself, and links back here so this page stays the table of contents. Hit an error you don’t see? Send it through the PeopleAreGeek contact channel and I’ll add it, assuming it isn’t already queued. A few kinds jump the line for me: ones with no clear good answer out there in 2026, and ones whose message lies to your face (the runtime blames one thing while the real cause sits somewhere else entirely). Anything that blocks a deploy or a production restart also goes straight to the top. What I’m not covering is “you forgot a semicolon” or “you typoed a variable”. Your linter and that red squiggle in your editor already have those covered, and they do it faster than I ever could anyway.

Frequently asked questions

How do you choose which errors to include?

Two things, mostly. How much people search it on Google over the last year, and how much it stings when it lands. An error that kills a deploy beats one that just nags you in local dev. The first eight are the high-frequency stuff across Node.js, Python, npm, browser fetch and reverse-proxy 5xx, because in my experience those rack up the most “wait, why am I stuck again” minutes per week.

Why not just link to Stack Overflow for each?

Stack Overflow shines when the problem is actually new. For the same tired errors that keep coming back, though, the real cost is sifting through a heap of answers and working out which one still holds up today. So I traded discovery for curation. I’ve read every entry here myself and I keep them current against the tooling people are actually running.

How often is each entry reviewed?

Twice a year at the absolute minimum. Right away whenever a major version of the runtime drops (a fresh Node.js LTS, say). And any time a reader pings me that a snippet’s gone stale. As the hub fills out, every entry will carry its own “last verified” date, so you’re never left guessing how fresh it is.

Can I suggest an error to add?

Please do. Drop the error code and a one-line description to contact@peoplearegeek.com. The ones I push to the front pull at least 1,000 searches a month and still don’t have a clear winning answer on Google. Those are the ones worth writing up.

Is this hub language-agnostic?

For now it leans web. I started with Node.js, Python, npm, browser fetch and Nginx because between them they cover most of what a modern web-app stack throws at you. Go, Rust, Java and Kubernetes are already lined up for next quarter, so it won’t stay this narrow. I’d rather go deep on a handful of stacks first than spread thin across twenty, even if that takes longer.

Do I need to sign up to use the hub?

Nope. It’s free and public, no account, and I’m not tracking a single thing you type. The search and the filters run entirely inside your own browser. Whatever you paste in that box never reaches me.

Sources & further reading

  • MDN Web Docs

Related tools and resources

HTTP Status Code Explainer CDN Detector HTTP Headers Checker Redirect Checker JSON Formatter Regex Tester Timestamp Converter
ShareTweetPin
People Are Geek

People Are Geek

I'm Stephane, a network and systems engineer with over 15 years of hands-on experience on production infrastructure, virtualization (ESXi, Proxmox), networking, and self-hosting. Earlier in my career I built and ran a Linux resource site that became a well-known reference for sysadmins. Today I focus on cybersecurity, and I also work as a technical trainer, teaching networking and security to people who do it for a living. Everything on People Are Geek comes from real-world practice, not theory. I build every tool on this site myself, and I write about what I've actually deployed, broken, and fixed. If it's here, I've used it.

People Are Geek

Copyright © 2017 JNews.

Navigate Site

  • About PeopleAreGeek
  • Affiliate Disclosure
  • All Tools and Articles
  • Contact
  • Cookie Policy
  • Hyper-V Hub: Tools, Error Fixes and Lab Guides
  • Linux Hub: Cross-Distro Reference, Articles, Tools
  • Privacy Policy
  • Sample Page
  • Terms of Service
  • VMware vSphere & ESXi Hub: Tools, Error Fixes and Guides

Follow Us

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools

Copyright © 2017 JNews.