upstash/context7 · error · Error
describeConnectionError(error, url)
Error message
describeConnectionError(error, url)
What it means
`postForm` wraps any `fetch` rejection during OAuth calls into a single descriptive Error built by `describeConnectionError`: `Could not reach {url}: {detail} ({code})` plus a remediation hint selected from the underlying cause code — TLS hints for certificate errors, DNS_HINT for ENOTFOUND/EAI_AGAIN, BLOCKED_HINT for ECONNREFUSED/ECONNRESET/EHOSTUNREACH, TIMEOUT_HINT for ETIMEDOUT/UND_ERR_CONNECT_TIMEOUT. The original network error is swallowed; only this message survives.
Source
Thrown at packages/cli/src/utils/auth.ts:214
}
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 5284672feb)
Solutions
- For TLS errors, point NODE_EXTRA_CA_CERTS at your organization's root CA certificate
- For DNS errors (ENOTFOUND/EAI_AGAIN), fix resolver/VPN or wait for network
- Node fetch ignores HTTPS_PROXY — configure an undici ProxyAgent dispatcher if you must go through a proxy
- Verify basic reachability: curl -v <baseUrl>/ping from the same environment
Example fix
# before: behind corporate proxy, fetch fails opaquely context7 login # after: trust the proxy's root CA and route via undici export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/corp-root.pem export HTTPS_PROXY=http://proxy.corp:3128 # needs an undici ProxyAgent in code
Defensive patterns
Strategy: retry
Validate before calling
// Preflight: DNS + TCP reachability before starting OAuth
import { promises as dns } from 'dns';
async function hostReachable(url: string): Promise<boolean> {
try { await dns.lookup(new URL(url).hostname); return true; } catch { return false; }
} Try / catch
try {
await postForm(url, params);
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
if (/ENOTFOUND|EAI_AGAIN/.test(msg)) throw new Error('DNS failure — check VPN/resolver');
if (/ETIMEDOUT|UND_ERR_CONNECT_TIMEOUT/.test(msg)) await sleep(2000); // retry once
else throw error;
} Prevention
- Export NODE_EXTRA_CA_CERTS in corporate proxy environments before any login
- Node fetch ignores HTTPS_PROXY — configure an undici ProxyAgent dispatcher explicitly
- Run a connectivity check to the API host before starting interactive OAuth flows
When it happens
Trigger: Any `context7 login` / token refresh where DNS fails (ENOTFOUND, EAI_AGAIN), a TLS-intercepting proxy breaks cert verification (UNABLE_TO_VERIFY_LEAF_SIGNATURE, SELF_SIGNED_CERT_IN_CHAIN), a firewall resets the connection (ECONNRESET, ECONNREFUSED), or the connect times out (UND_ERR_CONNECT_TIMEOUT, ETIMEDOUT).
Common situations: Corporate MITM proxy without NODE_EXTRA_CA_CERTS set to the org root CA; VPN split-tunnel DNS; Node's fetch silently ignoring HTTPS_PROXY (it does not use it automatically); captive portal; offline machine.
Related errors
- proxy_error
- downloadData.error || "no files"
- await describeErrorResponse(response, fallback)
- err.error_description || err.error || "Device token poll fai
- Failed to download ${skill.name}: ${downloadData.error}
AI-assisted analysis of upstash/context7@5284672feb (2026-08-18).
Data as JSON: /api/errors/be7968bc4b378faa.
Report an issue: GitHub.