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

QwenCloud Token Plan

Error message

QwenCloud Token Plan

What it means

loginAlibabaTokenPlan (QwenCloud Token Plan) is an interactive login that needs an onPrompt callback to ask which region endpoint to use (International/China Beijing/Custom). Without an onPrompt function on the OAuthController it throws OnPromptRequiredError('QwenCloud Token Plan') so the embedding application knows it must provide user interaction.

Source

Thrown at packages/ai/src/registry/alibaba-token-plan.ts:27

import type { ProviderDefinition } from "./types";

const INTERNATIONAL_AUTH_URL = "https://home.qwencloud.com/billing/subscription/token-plan-individual";
const CHINA_AUTH_URL = "https://www.aliyun.com/benefit/scene/tokenplan";

/**
 * Log in to the QwenCloud Token Plan provider.
 *
 * The Token Plan ships as two regionally separate products with
 * non-interchangeable keys — International (Singapore) and China (Beijing) —
 * so login first selects the region (or a custom base URL) before pasting the
 * key, mirroring {@link loginAlibabaCodingPlan}. The chosen region is validated
 * against its own `/models` endpoint and, when it diverges from the default
 * international endpoint, stored in the credential so inference and discovery
 * both target it (#6682).
 */
export async function loginAlibabaTokenPlan(options: OAuthController): Promise<string> {
	if (!options.onPrompt) {
		throw new AIError.OnPromptRequiredError("QwenCloud Token Plan");
	}

	const endpointChoice = await options.onPrompt({
		message:
			"Select QwenCloud Token Plan region: 1=International (default), 2=China (Beijing), 3=Custom — enter 1, 2, or 3",
		placeholder: "1",
	});
	if (options.signal?.aborted) {
		throw new AIError.LoginCancelledError();
	}

	const choice = endpointChoice.trim();
	let baseUrl: string;
	let authUrl: string;
	let instructions: string;
	if (choice === "2") {
		baseUrl = ALIBABA_TOKEN_PLAN_CN_BASE_URL;
		authUrl = CHINA_AUTH_URL;

View on GitHub (pinned to 9690622007)

Solutions

  1. Provide an OAuthController with an `onPrompt` implementation
  2. Run login via the interactive CLI/agent that supplies prompt UI
  3. Set up the Token Plan credential manually (API key in config) for unattended environments

Example fix

// before
await loginAlibabaTokenPlan(controllerWithoutPrompts);
// after
await loginAlibabaTokenPlan({ ...controller, onPrompt: async q => promptUser(q.message) });
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof controller?.onPrompt !== 'function') throw new Error('QwenCloud Token Plan login requires an interactive onPrompt callback');

Type guard

function canPrompt(c: OAuthController): c is OAuthController & { onPrompt: NonNullable<OAuthController['onPrompt']> } { return typeof c.onPrompt === 'function'; }

Try / catch

try { key = await loginAlibabaTokenPlan(controller); } catch (e) { if (e instanceof AIError.OnPromptRequiredError) key = await provisionKeyFromConfig(); else throw e; }

Prevention

When it happens

Trigger: Calling loginAlibabaTokenPlan with an options object lacking `onPrompt` — headless scripts, SDK embedding without prompt wiring, or a controller constructed without prompt hooks.

Common situations: CI/CD credential bootstrap; non-TTY environments; forgetting that token-plan login, unlike plain API-key setup, is region-interactive.

Related errors


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