can1357/oh-my-pi · warning · Error

Smithery login cancelled. Run /mcp smithery-login, then retr

Error message

Smithery login cancelled. Run /mcp smithery-login, then retry /mcp smithery-search.

What it means

Thrown by #requireSmitheryApiKey when no stored Smithery API key exists, the interactive login prompt (#promptSmitheryLogin) returns false (the browser login failed and the API-key fallback was also declined), and therefore no key can be supplied for the pending Smithery operation (search/install). It is the user-facing 'you must authenticate to proceed' error, with instructions embedded in the message.

Source

Thrown at packages/coding-agent/src/modes/controllers/mcp-command-controller.ts:2493

	#getSmitheryErrorStatus(error: unknown): number | undefined {
		if (error instanceof SmitheryRegistryError || error instanceof SmitheryConnectError) {
			return error.status;
		}
		return undefined;
	}

	#toSmitheryAuthReason(status: number): string {
		return status === 429 ? "rate limited by Smithery" : "forbidden/unauthorized with Smithery";
	}

	async #requireSmitheryApiKey(reason: string): Promise<string> {
		let apiKey = await getSmitheryApiKey();
		if (apiKey) return apiKey;

		const loggedIn = await this.#promptSmitheryLogin(reason);
		if (!loggedIn) {
			throw new Error("Smithery login cancelled. Run /mcp smithery-login, then retry /mcp smithery-search.");
		}

		apiKey = await getSmitheryApiKey();
		if (!apiKey) {
			throw new Error("Smithery API key not found after login.");
		}
		return apiKey;
	}

	async #runSmitheryOperationWithAuthRetry<T>(operation: (apiKey: string) => Promise<T>, reason: string): Promise<T> {
		const apiKey = await this.#requireSmitheryApiKey(reason);
		try {
			return await operation(apiKey);
		} catch (error) {
			const status = this.#getSmitheryErrorStatus(error);
			if (status === undefined || ![401, 403, 429].includes(status)) {
				throw error;
			}

View on GitHub (pinned to 9690622007)

Solutions

  1. Run /mcp smithery-login and complete it (browser auth or paste your API key from smithery.ai), then retry the original command.
  2. If the browser never opens, copy the 'Authorize URL' printed in the message panel and open it manually.
  3. Get an API key at smithery.ai (account settings) if you don't have one, then paste it at the prompt.
Defensive patterns

Strategy: validation

Validate before calling

const apiKey = await getSmitheryApiKey();
if (!apiKey) {
  console.log("No Smithery key stored. Run /mcp smithery-login first (browser auth or paste your key from smithery.ai).");
}

Type guard

function isLoginCancelledError(err: unknown): err is Error {
  return err instanceof Error && err.message.startsWith("Smithery login cancelled");
}

Try / catch

try {
  await smitherySearch(query);
} catch (err) {
  if (isLoginCancelledError(err)) {
    // user declined login: surface the retry instruction instead of a stack
    showHint("Run /mcp smithery-login, then retry /mcp smithery-search.");
  } else throw err;
}

Prevention

When it happens

Trigger: Running /mcp smithery-search (or any Smithery operation via #runSmitheryOperationWithAuthRetry) with no API key saved, then cancelling the login prompt — either by pressing Esc at the API-key input, or the browser auth failing and the key entry being aborted.

Common situations: User has no Smithery account/key yet; popup blocked so browser auth never opens and the user Escapes out of the fallback prompt; headless environment with no browser and the user not ready to paste a key.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


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