upstash/context7 · error

Could not reach : )` : ""}\n

Error message

Could not reach ${url}: ${detail}${code ? ` (${code})` : ""}\n${hint}

What it means

Thrown by postForm when the underlying fetch to an OAuth endpoint (token exchange, device authorization, refresh) fails at the network level — DNS failure, connection refused, timeout, TLS error, etc. The raw fetch error is passed to describeConnectionError, which produces a human-readable message including the URL, the failure detail, the optional error code, and a hint. This converts opaque undici/network errors into actionable messages for CLI users.

Solutions

  1. Check network connectivity and retry the login/command
  2. Verify the auth base URL is correct and resolvable (the URL in the message tells you which host failed)
  3. Check proxy/VPN/firewall settings — set HTTPS_PROXY if your network requires it, or allowlist the auth domain
  4. Check the auth service status or retry later if it's a server-side outage

Example fix

// before: failing in a proxied environment
await fetch(url, { method: "POST", body: params.toString() });
// after: rely on proxy env vars / add timeout handling
await fetch(url, {
  method: "POST",
  body: params.toString(),
  signal: AbortSignal.timeout(15000),
});
Defensive patterns

Strategy: retry

Validate before calling

// probe reachability before the OAuth call
try {
  await fetch(baseUrl, { method: "HEAD", signal: AbortSignal.timeout(5000) });
} catch (e) {
  throw new Error(`Auth server unreachable at ${baseUrl}: ${e.cause?.code ?? e.message}`);
}

Try / catch

let lastErr;
for (let attempt = 0; attempt < 3; attempt++) {
  try { return await startOAuthFlow(); }
  catch (e) {
    lastErr = e;
    if (!/Could not reach/.test(e.message)) throw e; // only retry network errors
    await new Promise(r => setTimeout(r, 2 ** attempt * 1000));
  }
}
throw lastErr;

Prevention

When it happens

Trigger: Any OAuth flow call (oauthRequest, pollDeviceToken, token refresh) that invokes postForm while the auth server is unreachable: offline machine, wrong base URL, DNS misconfiguration, blocked firewall/proxy, or the auth server being down.

Common situations: Corporate proxies intercepting TLS, VPN required to reach the auth host, typo'd domain in auth configuration, no internet in CI, or transient server outage during device-code login.

Related errors


AI-assisted analysis of upstash/context7@4416fb855b (2026-09-16). Data as JSON: /api/errors/989b1e532ba98e29. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/utils/auth.ts:221

}

function describeConnectionError(error: unknown, url: string): string {
  const { code, message } = getErrorCause(error);
  const detail = message || (error instanceof Error ? error.message : String(error));
  const hint = (code && CONNECTION_HINTS[code]) || DEFAULT_HINT;

  return `Could not reach ${url}: ${detail}${code ? ` (${code})` : ""}\n${hint}`;
}

async function postForm(url: string, params: URLSearchParams): Promise<Response> {
  try {
    return await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: params.toString(),
    });
  } catch (error) {
    throw new Error(describeConnectionError(error, url));
  }
}

async function oauthRequest<T>(url: string, params: URLSearchParams, fallback: string): Promise<T> {
  const response = await postForm(url, params);
  if (!response.ok) {
    throw new Error(await describeErrorResponse(response, fallback));
  }
  return (await response.json()) as T;
}

/** RFC 8628 §3.2 default poll interval when the server omits `interval`. */
export const DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 5;

export async function startDeviceAuthorization(
  baseUrl: string,
  clientId: string
): Promise<DeviceAuthorizationResponse> {

View on GitHub (pinned to 4416fb855b)