can1357/oh-my-pi · error · Error

Unrecognized source format. Did you mean './${source}' (loca

Error message

Unrecognized source format. Did you mean './${source}' (local) or 'owner/repo' (GitHub)?

What it means

classifySource recognizes exactly four source forms: http(s) URLs, git@/ssh:// URLs, GitHub owner/repo shorthand, and local paths (./, ~/, absolute POSIX or Windows). Any string matching none of these throws this error with a suggestion to prefix with ./ (local) or use owner/repo (GitHub).

Source

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

		return "git";
	}

	// Rule 3: GitHub owner/repo shorthand (no protocol, no leading slash)
	if (GITHUB_SHORTHAND_RE.test(source)) {
		return "github";
	}

	// Rule 4: Explicit relative or home-relative paths
	if (source.startsWith("./") || source.startsWith("~/")) {
		return "local";
	}

	// Rule 5: Absolute paths — POSIX via path.isAbsolute, Windows via regex
	if (path.isAbsolute(source) || WIN_ABS_RE.test(source)) {
		return "local";
	}

	throw new Error(`Unrecognized source format. Did you mean './${source}' (local) or 'owner/repo' (GitHub)?`);
}

// ── parseMarketplaceCatalog ───────────────────────────────────────────

function assertField(condition: boolean, field: string, filePath: string): void {
	if (!condition) {
		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.

View on GitHub (pinned to 9690622007)

Solutions

  1. Prefix relative paths with "./" (or "../") so they classify as local.
  2. Use "owner/repo" shorthand for GitHub marketplaces.
  3. Use an absolute path or "~/"-prefixed path for local directories.
  4. Use a full https:// URL for remote catalogs.

Example fix

// before
classifySource("marketplaces/acme"); // unrecognized
// after
classifySource("./marketplaces/acme"); // local
// or
classifySource("acme/marketplace"); // GitHub shorthand
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeSource(s: string): boolean {
  return /^(https?:\/\/|git@|ssh:\/\/)\S+/.test(s)
    || /^[a-z0-9-]+\/[a-z0-9._-]+$/i.test(s)
    || s.startsWith("./") || s.startsWith("../") || s.startsWith("~/")
    || path.isAbsolute(s);
}

Try / catch

try {
  const type = classifySource(source);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Unrecognized source format")) {
    console.error(`"${source}" — use ./rel/path, /abs/path, owner/repo, or https://...`);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a bare relative path without ./ (e.g. "marketplace.json", "../mkt"); single-token names like "mymarketplace" (no slash, so not owner/repo); URLs with non-http protocols (file://, git://); names with multiple slashes or illegal chars that fail GITHUB_SHORTHAND_RE.

Common situations: Users typing a relative directory/file name and omitting ./; paths like "~/.." written without the tilde prefix handled form; Windows drive paths on POSIX hosts without backslashes handled by WIN_ABS_RE edge cases; downstream config files storing unnormalized source strings.

Related errors


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