can1357/oh-my-pi · error · Error

Invalid Firecrawl base URL: expected an HTTP or HTTPS URL

Error message

Invalid Firecrawl base URL: expected an HTTP or HTTPS URL

What it means

resolveSearchUrl() validates the Firecrawl base URL configured via FIRECRAWL_BASE_URL or FIRECRAWL_API_URL before building the /search endpoint. This variant is thrown when the configured value cannot be parsed by `new URL()` at all — it is not a syntactically valid absolute URL. The provider refuses to guess a base and fails fast so requests never go to a malformed endpoint.

Source

Thrown at packages/coding-agent/src/web/search/providers/firecrawl.ts:40

const FIRECRAWL_DEFAULT_BASE_URL = "https://api.firecrawl.dev/v2";
const DEFAULT_NUM_RESULTS = 10;
const MAX_NUM_RESULTS = 100;

const RECENCY_TBS: Record<NonNullable<SearchParams["recency"]>, string> = {
	day: "qdr:d",
	week: "qdr:w",
	month: "qdr:m",
	year: "qdr:y",
};
function resolveSearchUrl(): string {
	const configured = process.env.FIRECRAWL_BASE_URL ?? process.env.FIRECRAWL_API_URL;
	if (!configured?.trim()) return `${FIRECRAWL_DEFAULT_BASE_URL}/search`;
	let url: URL;
	try {
		url = new URL(configured.trim());
	} catch {
		throw new Error("Invalid Firecrawl base URL: expected an HTTP or HTTPS URL");
	}
	if (url.protocol !== "http:" && url.protocol !== "https:") {
		throw new Error("Invalid Firecrawl base URL: expected an HTTP or HTTPS URL");
	}
	if (url.username || url.password) {
		throw new Error("Invalid Firecrawl base URL: URL credentials are not allowed");
	}
	url.search = "";
	url.hash = "";
	url.pathname = url.pathname.replace(/\/+$/, "");
	if (!/\/v[12]$/i.test(url.pathname)) url.pathname += "/v2";
	url.pathname += "/search";
	return url.toString();
}

export interface FirecrawlSearchParams {
	query: string;
	num_results?: number;

View on GitHub (pinned to 9690622007)

Solutions

  1. Set FIRECRAWL_BASE_URL to a fully-qualified absolute URL including the scheme, e.g. http://localhost:3002 or https://api.firecrawl.dev
  2. If you meant to use the hosted API, unset both FIRECRAWL_BASE_URL and FIRECRAWL_API_URL so the default https://api.firecrawl.dev is used
  3. Check .env / shell export for stray quotes, trailing whitespace, or line-continuation characters corrupting the value

Example fix

// before
FIRECRAWL_BASE_URL=localhost:3002
// after
FIRECRAWL_BASE_URL=http://localhost:3002
Defensive patterns

Strategy: validation

Validate before calling

function isValidFirecrawlBaseUrl() {
  const v = process.env.FIRECRAWL_BASE_URL ?? process.env.FIRECRAWL_API_URL;
  if (!v?.trim()) return true; // default applies
  try {
    const u = new URL(v.trim());
    return u.protocol === "http:" || u.protocol === "https:";
  } catch {
    return false;
  }
}
if (!isValidFirecrawlBaseUrl()) throw new Error("Fix FIRECRAWL_BASE_URL: must be an absolute http(s) URL");

Type guard

function isHttpUrl(value: string): value is string {
  try {
    const u = new URL(value);
    return u.protocol === "http:" || u.protocol === "https:";
  } catch {
    return false;
  }
}

Try / catch

try {
  await firecrawlSearch(query);
} catch (err) {
  if (err instanceof Error && err.message.includes("Invalid Firecrawl base URL")) {
    logger.error("Firecrawl configuration invalid — check FIRECRAWL_BASE_URL", { cause: err.message });
    // fall back to default provider or abort startup
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: FIRECRAWL_BASE_URL or FIRECRAWL_API_URL is set to something `new URL(value.trim())` rejects: a bare hostname like 'localhost:3002' with no scheme is fine but 'localhost' alone, 'my-firecrawl.internal' (no protocol), a value with stray spaces/tabs that survive after trim, or an empty-ish value that passed the trim check but is unparsable.

Common situations: Self-hosted Firecrawl users setting FIRECRAWL_BASE_URL=localhost:3002 (forgot http://), paste errors adding quotes or whitespace into env files, or a deploy system injecting a placeholder value like 'CHANGE_ME'.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/5d64d5d5cfcbfb40. Report an issue: GitHub.