ApolloError “Only absolute URLs are supported” means Apollo tried to fetch a relative link in a server runtime, so your GraphQL URI must be a full http(s) URL.
If you’re seeing this during SSR, prerendering, or a CI build, it can feel random. Locally the page loads. Then a deploy fails and the log points at Apollo. In most cases the root cause is simple: the browser can resolve /graphql against the current site, while Node’s fetch stack can’t.
You’ll often spot the same message in different wrappers, including “Network error: Only absolute URLs are supported” or “TypeError: Only absolute URLs are supported.” The fix is still the same. Find the place where Apollo builds the request URL and make it absolute for any server-side request.
What The Error Means And When It Pops Up
An absolute URL includes a scheme and a host, like https://api.example.com/graphql. A relative URL is missing that base, like /graphql or graphql. Browsers can fill in the missing parts because they know the current page’s origin. A server runtime has no page origin, so it can’t guess what “/graphql” is supposed to mean.
When Apollo runs a query, it hands the link to fetch (or to a fetch-like layer). If that layer is running on the server, a relative endpoint will trigger the error. That’s why this often appears only on refresh, build, or SSR routes, even if client-side navigation seems fine.
| Where You See It | Most Common Cause | Fast Fix |
|---|---|---|
| Next.js SSR or SSG build | Apollo HttpLink uses /graphql |
Use https://…/graphql on the server |
| Node scripts or tests | Schema load or query uses a relative URL | Pass a full endpoint via config or env var |
| Vercel, Netlify, Cloud Run | Base URL differs from local setup | Set a site URL var and build the endpoint from it |
| Proxy or reverse proxy | Request gets a path, not a full URL | Build origin from request headers with a safe allowlist |
If your log includes the exact phrase apolloerror only absolute urls are supported, treat it as a signal that some server-side code path is firing. That can be full SSR, static generation, an API route, or even a background job that reuses your Apollo setup.
ApolloError Only Absolute URLs Are Supported In SSR Builds
SSR is where this bug loves to hide. On the server, Apollo can’t rely on the browser’s current origin, so you need to give it a complete endpoint. Apollo’s own SSR guidance calls this out: relative network requests only work in a browser, so use an absolute URL for the server endpoint.
Start by locating where you create HttpLink (or createHttpLink) and look at the uri. If you see a path-only value like /api/graphql, that’s the red flag.
- Find the link URI — Search your code for
new HttpLink,createHttpLink, oruri:inside Apollo client setup. - Check server execution — In SSR code paths, confirm
typeof window === 'undefined'(or the equivalent) is true. - Swap in an absolute endpoint — On the server, set
urito something likehttps://your-domain.tld/graphql. - Keep the browser path tidy — In the browser, you can still use a relative path if you want, since the page origin exists.
Here’s a safe pattern that keeps the server strict and the browser simple. It uses one helper that always returns an absolute endpoint on the server.
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
function getGraphqlUri() {
// Browser navigation can use a path.
if (typeof window !== "undefined") return "/graphql";
// Server must use a full URL.
const base = process.env.SITE_URL;
if (!base) throw new Error("Missing SITE_URL for server Apollo");
return new URL("/graphql", base).toString();
}
export function makeApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: new HttpLink({ uri: getGraphqlUri() }),
cache: new InMemoryCache(),
});
}
This does two things that stop the error cold. First, it blocks SSR from using a path-only endpoint. Second, it forces you to set a known base URL in one place, so deploy-time surprises don’t creep in.
Fixing The ApolloError Absolute URL Problem In Apollo Client Setups
If you’re not doing SSR, you can still hit this message in server-side helpers, scripts, or tests. The pattern is the same: something is calling Apollo in a server context with a path-only URI.
Most teams fix it faster by treating the GraphQL URL as configuration, not as a hard-coded string. That means one source of truth, injected through an env var. It keeps local, staging, and production aligned without editing code between runs.
- Set a single endpoint var — Use
GRAPHQL_URLwith a full URL likehttps://api.example.com/graphql. - Validate it at startup — Parse the value with
new URL()and fail fast if it’s not valid. - Log the host in dev — Print only the origin or hostname to confirm you’re pointing at the right place.
Validation is worth the few lines. Without it, a missing protocol or a stray space can turn into a late crash in SSR. A quick parse catches that early.
function requireAbsoluteUrl(value, name) {
if (!value) throw new Error(`Missing ${name}`);
const url = new URL(value);
if (url.protocol !== "http:" && url.protocol !== "https:") {
throw new Error(`${name} must start with http:// or https://`);
}
return url.toString();
}
const GRAPHQL_URL = requireAbsoluteUrl(process.env.GRAPHQL_URL, "GRAPHQL_URL");
After you have a clean absolute URL, wire it into your HttpLink. This is the simplest fix for build systems, Jest tests, and one-off Node scripts that reuse your Apollo client.
Building A Server Base URL Without Getting Burned
Sometimes you can’t hard-code the base URL because the same build runs behind different domains. In that case, you’ll be tempted to read request headers and build the origin from them. That can work, but you should be picky about which header you trust.
Many platforms pass a forwarded protocol and host header. The danger is that host headers can be spoofed if you trust them blindly. If you go this route, use an allowlist of known hosts, or prefer a platform-provided base URL var when it exists.
- Prefer a configured base URL — Set
SITE_URLper deploy target when you can. - Use request headers only with checks — Match hostnames against a short allowlist you control.
- Normalize the protocol — Use
x-forwarded-protowhen present, then fall back tohttps.
This helper shows the shape. It keeps the logic tight and blocks unknown hosts. Replace the allowlist values with your real domains.
const ALLOWED_HOSTS = new Set([
"example.com",
"www.example.com",
"staging.example.com",
]);
export function originFromRequest(req) {
const host = String(req.headers.host || "").toLowerCase();
if (!ALLOWED_HOSTS.has(host)) throw new Error("Unexpected host header");
const proto = String(req.headers["x-forwarded-proto"] || "https").split(",")[0];
return `${proto}://${host}`;
}
Once you have the origin, you can build the endpoint with new URL("/graphql", origin). That yields a clean absolute URL every time, which is exactly what Apollo’s network layer expects on the server.
Next.js And Similar SSR Runtimes: Common Fix Patterns
Next.js apps hit this error a lot because they run code in two places. During client navigation, a relative path is fine. During getServerSideProps, route handlers, or build-time rendering, that same relative path becomes invalid.
Pick one of these patterns based on how your app is deployed. The goal is always the same: Apollo’s server-side fetch must point at an absolute endpoint.
- Use a public site URL var — Set
NEXT_PUBLIC_SITE_URLand buildnew URL("/graphql", NEXT_PUBLIC_SITE_URL)on the server. - Use a platform URL var — Many hosts provide a deploy URL; map it into your own
SITE_URLso your code stays portable. - Split browser and server URIs — Keep
/graphqlfor the browser and use a full URL for SSR.
One gotcha: when you run locally, your GraphQL API might live on the same origin. In production, the API might be on a different subdomain. Your relative path masks that difference until SSR tries to resolve it. Using an explicit base URL makes that mismatch visible early.
If you’re using the Edge runtime, treat it like server code for URL building. Edge still won’t have a browser origin, so the same absolute URL rule applies.
Tooling, Proxies, And Polyfills That Trigger The Same Message
This error isn’t limited to page renders. It can show up when you run tools that fetch a schema, generate types, or validate operations. Apollo’s tooling and other GraphQL tools can throw “Only absolute URLs are supported” if you point them at a relative endpoint.
It can also appear when a proxy layer rewrites URLs in a way that strips the scheme and host. Your app code may still look fine, while the effective URL that reaches fetch becomes path-only.
- Check CLI config endpoints — If a tool asks for a schema URL, give it a full
http(s)://link. - Confirm proxy rewrites — Make sure the final hop still sees an absolute URL where required.
- Verify fetch polyfills — In Node, libraries like
node-fetchexpect absolute URLs, so a relative string will fail fast.
If the error appears only after a package upgrade, scan your link chain. A new fetch implementation, a different transport, or a change in SSR defaults can make a hidden relative URL start crashing. The fix still comes down to the same move: make the URI absolute in every server-side path.
Quick Debug Checklist To Keep It From Returning
Once you fix the URL, lock it in with a small set of checks. This prevents the next refactor from reintroducing a path-only endpoint and breaking your deploy. It also saves time when a teammate copies a snippet that works only in the browser. That fix holds across refreshes.
- Print the final URI on SSR — Log just the origin and path during server startup, then remove it after confirmation.
- Add a unit test for URL shape — Assert that the server-side URI starts with
httpand contains your expected hostname. - Fail fast when vars are missing — Throw at startup if
SITE_URLorGRAPHQL_URLis empty. - Keep one builder function — Route every Apollo client creation through a shared helper.
- Recheck builds after deploy changes — A domain swap or proxy change can change what base URL you should use.
If you want a quick mental model, treat the phrase apolloerror only absolute urls are supported as a loud hint that some code ran outside the browser. Once your server paths always produce https://… URLs, the error stops showing up across SSR, builds, and scripts.
