upstash/context7 · error · Context7UrlError

invalid_url

invalid_url

Error message

Context7 client was passed an invalid URL. You should pass a URL starting with http:// or https://. Received: "${url}".

What it means

Context7UrlError (code "invalid_url") thrown in the client constructor when the baseUrl does not start with http:// or https://. The trailing slash is stripped first, then isHttpUrl validates the scheme.

Source

Thrown at packages/sdk/src/http/index.ts:57

    timeout: number | false;
    keepAlive: boolean;
  };
  public readonly retry: RetryPolicy;

  private readonly fetch: Context7Fetch;
  private readonly onResponse?: (metadata: Context7ResponseMetadata) => void;

  public constructor(config: HttpClientConfig) {
    this.options = {
      cache: config.cache,
      signal: config.signal,
      timeout: config.timeout ?? DEFAULT_TIMEOUT,
      keepAlive: config.keepAlive ?? true,
    };
    validateTimeout(this.options.timeout);

    this.baseUrl = config.baseUrl.replace(/\/$/, "");
    if (!isHttpUrl(this.baseUrl)) throw new Context7UrlError(this.baseUrl);

    this.headers = { "Content-Type": "application/json", ...config.headers };
    if (!config.fetch && !globalThis.fetch) {
      throw new TypeError("A fetch implementation is required");
    }
    this.fetch = config.fetch ?? globalThis.fetch.bind(globalThis);
    this.onResponse = config.onResponse;
    this.retry = createRetryPolicy(config.retry);
  }

  public async request<TResult>(request: Context7Request): Promise<Context7Response<TResult>> {
    const method = request.method ?? "POST";
    const abortState = createAbortState(
      [resolveSignal(this.options.signal), request.signal],
      request.timeout ?? this.options.timeout
    );
    const init: RequestInit = {
      cache: normalizeCache(request.cache ?? this.options.cache),

View on GitHub (pinned to 80e681a507)

Solutions

  1. Prefix the URL with https:// (or http:// for local dev): baseUrl: 'https://context7.com/api'.
  2. Validate the value before constructing: new URL(u) and check protocol is http: or https:.
  3. Fix the environment variable/config file so it contains the full absolute URL.
  4. Normalize trailing slashes if desired; the constructor already strips them — only the scheme matters.

Example fix

// before
new Context7Client({ baseUrl: process.env.CONTEXT7_URL }); // 'context7.com' -> invalid_url
// after
const raw = process.env.CONTEXT7_URL;
const baseUrl = raw.startsWith('http') ? raw : `https://${raw}`;
new Context7Client({ baseUrl });
Defensive patterns

Strategy: validation

Validate before calling

function assertHttpUrl(u: string): void {
  const parsed = new URL(u);
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
    throw new Error(`baseUrl must start with http:// or https://, got: ${u}`);
  }
}

Type guard

function isHttpUrl(u: string): boolean {
  try {
    const p = new URL(u);
    return p.protocol === 'http:' || p.protocol === 'https:';
  } catch {
    return false;
  }
}

Try / catch

try {
  const client = new Context7Client({ baseUrl });
} catch (e) {
  if (e instanceof Context7Error && e.code === 'invalid_url') {
    console.error(`Fix CONTEXT7_BASE_URL (needs scheme): ${e.message}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: new Context7Client({ baseUrl: 'context7.com/api' }) or 'localhost:8080' or an empty string — any URL without an http:// or https:// scheme.

Common situations: Omitting the scheme because browsers auto-complete it, reading baseUrl from env/config without scheme, accidentally passing a path or relative URL, or typos like 'hhttps://'.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of upstash/context7@80e681a507 (2026-09-08). Data as JSON: /api/errors/41ced66abaa6d06e. Report an issue: GitHub.