can1357/oh-my-pi · error · Error

Failed to parse marketplace catalog at ${filePath}: ${(err a

Error message

Failed to parse marketplace catalog at ${filePath}: ${(err as Error).message}

What it means

parseMarketplaceCatalog wraps JSON.parse failures when reading a marketplace catalog file. It means the catalog at the given path is not syntactically valid JSON. The underlying JSON parse message is appended so the exact syntax problem (unexpected token, bad escape, truncation) is visible.

Source

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

		throw new Error(`Missing or invalid field "${field}" in catalog: ${filePath}`);
	}
}

/**
 * Parse and validate a marketplace.json catalog from raw JSON content.
 *
 * Required fields: name (valid name segment), owner.name, plugins array.
 * Each plugin entry requires name (string) and source (string or object
 * with a "source" field). Extra fields are preserved via spread.
 *
 * @throws on JSON parse failure or missing/invalid required fields.
 */
export function parseMarketplaceCatalog(content: string, filePath: string): MarketplaceCatalog {
	let raw: unknown;
	try {
		raw = JSON.parse(content);
	} catch (err) {
		throw new Error(`Failed to parse marketplace catalog at ${filePath}: ${(err as Error).message}`);
	}

	if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
		throw new Error(`Marketplace catalog at ${filePath} must be a JSON object`);
	}

	const obj = raw as Record<string, unknown>;

	// name: required, must be a valid name segment
	assertField(typeof obj.name === "string" && isValidNameSegment(obj.name), "name", filePath);

	// owner: required object with name string
	assertField(typeof obj.owner === "object" && obj.owner !== null && !Array.isArray(obj.owner), "owner", filePath);
	const owner = obj.owner as Record<string, unknown>;
	assertField(typeof owner.name === "string", "owner.name", filePath);

	// plugins: required array
	assertField(Array.isArray(obj.plugins), "plugins", filePath);

View on GitHub (pinned to 9690622007)

Solutions

  1. Open the file at the reported path and fix the JSON syntax error indicated by the appended parse message (use a JSON linter or `bun -e 'JSON.parse(require("fs").readFileSync(path))'`).
  2. If the file was fetched from a URL, re-fetch and verify it returns application/json, not an HTML error page.
  3. Restore the catalog from the upstream marketplace repository or remove and re-add the marketplace so it is re-cloned.

Example fix

// before (catalog.json with trailing comma)
{ "name": "my-market", "plugins": [ ... ], }
// after
{ "name": "my-market", "plugins": [ ... ] }
Defensive patterns

Strategy: try-catch

Validate before calling

try { JSON.parse(content); } catch (e) { console.error(`Catalog content is not valid JSON: ${(e as Error).message}`); }

Try / catch

try {
  const catalog = parseMarketplaceCatalog(content, filePath);
} catch (err) {
  if ((err as Error).message.startsWith("Failed to parse marketplace catalog")) {
    // surface filePath + cause message, fall back to a default catalog or prompt re-fetch
  } else throw err;
}

Prevention

When it happens

Trigger: parseMarketplaceCatalog(content, filePath) called with content that JSON.parse rejects: malformed JSON from a manual edit, an HTML error page saved as catalog.json, a truncated download, or comments/trailing commas in the file.

Common situations: Hand-editing the catalog JSON and leaving a trailing comma; a proxy or captive portal returning an HTML error page that got saved to the catalog path; a partial git clone/file sync leaving a truncated file; editing on Windows introducing a BOM or smart quotes.

Understand the failure class

Related errors


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