can1357/oh-my-pi · error · AIError.ApiKeyRequiredError

Qwen token/API key is required

Error message

Qwen token/API key is required

What it means

loginQwenPortal requires a non-empty Qwen token or API key. When the user submits an empty (or whitespace-only) string at the prompt, it throws AIError.ApiKeyRequiredError with the message "Qwen token/API key is required". The library refuses to continue to credential validation with an empty secret.

Source

Thrown at packages/ai/src/registry/qwen-portal.ts:31

	}

	options.onAuth?.({
		url: AUTH_URL,
		instructions: "Copy your Qwen OAuth token or API key",
	});

	const token = await options.onPrompt({
		message: "Paste your Qwen OAuth token or API key",
		placeholder: "sk-...",
	});

	if (options.signal?.aborted) {
		throw new AIError.LoginCancelledError();
	}

	const trimmed = token.trim();
	if (!trimmed) {
		throw new AIError.ApiKeyRequiredError("Qwen token/API key is required");
	}

	options.onProgress?.("Validating credentials...");
	await validateOpenAICompatibleApiKey({
		provider: "qwen-portal",
		apiKey: trimmed,
		baseUrl: API_BASE_URL,
		model: VALIDATION_MODEL,
		signal: options.signal,
	});

	return trimmed;
}

export const qwenPortalProvider = {
	id: "qwen-portal",
	name: "Qwen Portal",
	login: (cb: OAuthLoginCallbacks) => loginQwenPortal(cb),

View on GitHub (pinned to 9690622007)

Solutions

  1. Ensure the prompt UI collects an actual token (Qwen OAuth token or sk-... API key) and re-run loginQwenPortal.
  2. Add pre-submit validation in the onPrompt UI to prevent submitting an empty value.
  3. If driving programmatically, make the onPrompt implementation return the real credential or throw a distinct cancellation error instead of "".
  4. Run `qwen` OAuth flow (device/portal) to obtain a valid token before attempting login.

Example fix

// before
await loginQwenPortal({ onPrompt: async () => clipboard.readText() ?? "", onProgress });
// after
await loginQwenPortal({
  onPrompt: async () => {
    const t = clipboard.readText()?.trim();
    if (!t) throw new Error("clipboard-empty");
    return t;
  },
  onProgress,
});
Defensive patterns

Strategy: validation

Validate before calling

const token = await options.onPrompt({ message: "Paste your Qwen OAuth token or API key", placeholder: "sk-..." });
if (!token || !token.trim()) {
  // re-prompt or abort before calling loginQwenPortal internals
  throw new Error("token-empty");
}

Try / catch

try {
  await loginQwenPortal({ onPrompt, signal });
} catch (err) {
  if (err instanceof AIError.ApiKeyRequiredError) {
    ui.notify("A Qwen token or API key is required.");
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: The onPrompt callback resolves with an empty string or whitespace-only string, so trimmed is empty and the guard throws.

Common situations: User just presses Enter at the paste prompt; clipboard paste silently failed so the input is blank; a scripted/automated caller wires onPrompt to something that returns "".

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/6e711c0e040343e3. Report an issue: GitHub.