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
- Provide an OAuthController with an `onPrompt` implementation
- Run login via the interactive CLI/agent that supplies prompt UI
- 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
- Construct controllers via a shared factory that always wires onPrompt
- Use config-file keys instead of interactive login in CI
- Note that token-plan login is region-interactive and not headless-safe
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
- Alibaba Coding Plan
- ${providerLabel} login requires onPrompt callback
- Unknown OAuth provider: ${provider}
- OAuth provider "${provider}" does not support token refresh
- Custom URL is required for option 3
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/39a76306e8e08327.
Report an issue: GitHub.