← Debugging Guides

阅读中文版本

Node.js ERR_INVALID_URL — TypeError Invalid URL

Fix the Node.js TypeError [ERR_INVALID_URL] when fetch or the WHATWG URL constructor rejects a relative, malformed, or protocol-less URL string.

beginnerdebuggingnodefetchhttp

Symptoms

  • TypeError [ERR_INVALID_URL]: Invalid URL
  • global fetch throws when given a relative path or a host without scheme
  • new URL(input) fails but the value looks like an address

Possible causes

  • A relative path such as /api/users is passed where an absolute URL is required
  • The string lacks a scheme (example.com instead of https://example.com)
  • User input was concatenated without encoding, producing spaces or stray characters
  • An environment variable used as the base URL is empty or malformed

Diagnosis steps

Print the exact value passed to fetch or new URL

console.log(JSON.stringify(url))

Interpretation

JSON.stringify reveals hidden spaces, missing slashes, or an empty string that console.log would hide.

Construct the URL with a base to accept relative paths

new URL(path, 'https://api.example.com')

Interpretation

If it succeeds with a base, the value was relative and needs an origin on the server side.

Validate the scheme with a regex before network calls

/^https?:\/\//.test(url)

Interpretation

Protocol-less values are the most common cause in Node, where fetch has no page context to resolve them.

Root cause

The WHATWG URL parser Node uses is strict: it requires an absolute URL with a scheme, and the WHATWG fetch adds no base for relative paths (unlike a browser page). Any relative, empty, or malformed string is rejected before a request is attempted.

Fix

Build absolute URLs from a configured base and encode dynamic segments with encodeURIComponent. Validate required environment variables at startup, and refuse to call fetch when the string does not parse. For relative paths, resolve against the known API origin explicitly.

Verify the fix

Log the parsed URL object before each request and run the failing code path; the URL parses, the request is sent, and no ERR_INVALID_URL is thrown.

Symptoms

Calling fetch('/api/users') or new URL(host) throws TypeError [ERR_INVALID_URL]. The value frequently looks valid until you inspect its bytes. In a browser the same relative string works because the page supplies a base, which is why this error is surprising on the server.

Diagnosis

Dump the raw value with escaping so whitespace is visible:

console.log(JSON.stringify(input));

Test whether a base resolves it:

new URL('/api/users', 'https://api.example.com'); // works
new URL('/api/users'); // throws

Fix

Always construct from a base and encode segments:

const base = process.env.API_BASE || 'https://api.example.com';
const url = new URL(`/users/${encodeURIComponent(id)}`, base);
await fetch(url);

Validate API_BASE at startup so a missing scheme fails fast.

Verification

Log the parsed url.href before each call. Requests now reach the server and the invalid-URL error no longer appears.

Common Traps

A trailing space after a copied URL, a missing scheme in an environment variable, and a Windows path passed where a URL is expected are the three most frequent triggers seen in production logs. Building every request with new URL(path, base) and logging href catches all three at the call site, because the parser normalises the result and an invalid composition fails immediately instead of deep inside the request layer.