can1357/oh-my-pi · error · Error

Failed to fetch marketplace catalog from ${source}: HTTP ${r

Error message

Failed to fetch marketplace catalog from ${source}: HTTP ${response.status} ${response.statusText}

What it means

fetchMarketplace performs an HTTP GET of a URL-type marketplace source with a 60-second timeout and throws this when the response status is not OK (2xx). The message includes the URL, HTTP status code, and status text so the exact server rejection is visible.

Source

Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/fetcher.ts:267

		const resolved = path.resolve(expandHome(source));
		const { catalogPath, content } = await readMarketplaceCatalog(resolved);
		const catalog = parseMarketplaceCatalog(content, catalogPath);
		return { catalog };
	}

	if (type === "github") {
		const url = `https://github.com/${source}.git`;
		return cloneAndReadCatalog(url, source, cacheDir);
	}

	if (type === "git") {
		return cloneAndReadCatalog(source, source, cacheDir);
	}

	// type === "url"
	const response = await fetch(source, { signal: AbortSignal.timeout(60_000) });
	if (!response.ok) {
		throw new Error(
			`Failed to fetch marketplace catalog from ${source}: HTTP ${response.status} ${response.statusText}`,
		);
	}
	const text = await response.text();
	const catalog = parseMarketplaceCatalog(text, source);

	const catalogDir = path.join(cacheDir, catalog.name);
	await Bun.write(path.join(catalogDir, "marketplace.json"), text);

	return { catalog };
}

// ── cloneAndReadCatalog ───────────────────────────────────────────────

/**
 * Clone a git repository and read its marketplace catalog.
 *
 * Clones to a temporary directory and reads the catalog. The caller is

View on GitHub (pinned to 9690622007)

Solutions

  1. Open the URL in a browser or with `curl -I` and confirm it returns 200 with JSON; fix the URL (use the raw content URL for GitHub-hosted catalogs).
  2. If the resource requires authentication, use a source type that supports credentials (e.g. git source with configured auth) instead of a plain URL.
  3. If the catalog moved, update the source or remove and re-add the marketplace with the new URL; retry later for transient 5xx errors.

Example fix

// before: HTML page URL
await fetchMarketplace("https://github.com/org/repo/blob/main/marketplace.json", cacheDir);
// after: raw content URL
await fetchMarketplace("https://raw.githubusercontent.com/org/repo/main/marketplace.json", cacheDir);
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(url, { method: "HEAD" });
if (!res.ok) throw new Error(`Catalog URL unreachable: HTTP ${res.status}`);

Try / catch

try {
  const catalog = await fetchMarketplace(url, cacheDir);
} catch (err) {
  if ((err as Error).message.includes("HTTP ")) {
    const status = Number((err as Error).message.match(/HTTP (\d+)/)?.[1]);
    if (status >= 500) { /* retry with backoff */ }
    else { /* fix URL / auth — do not retry 4xx */ }
  } else throw err;
}

Prevention

When it happens

Trigger: fetchMarketplace("https://...") where the server returns 404 (wrong URL), 403 (private repo/forbidden), 500 (server error), or any other non-2xx status.

Common situations: A typo in the raw catalog URL; pointing at an HTML page instead of the raw JSON (e.g. a GitHub blob page instead of raw.githubusercontent.com); the catalog was moved/renamed upstream; a private URL without credentials; corporate proxy blocking the request.

Related errors


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