jackwener/OpenCLI · error · ArgumentError
${wantModel} model requires a paid Claude plan.
Error message
${wantModel} model requires a paid Claude plan. What it means
selectModel() reported the requested model is gated behind a paid plan (modelResult.upgrade). The library converts that into an ArgumentError telling the user the chosen model (e.g. opus) requires a paid Claude subscription and suggesting sonnet or haiku instead.
Source
Thrown at clis/claude/ask.js:89
// an existing conversation. Also avoid changing the user's current
// UI selection unless --model was explicitly passed.
const currentUrl = await page.evaluate('window.location.href') || '';
const inConversation = currentUrl.includes('/chat/');
const modelExplicit = kwargs.__opencliOptionSources?.model === 'cli';
const wantModel = kwargs.model || 'sonnet';
if (modelExplicit) {
if (inConversation) {
throw new ArgumentError(
`Cannot switch to ${wantModel} model inside an existing conversation.`,
'Re-run with --new to start a fresh chat before selecting a model.',
);
}
const modelResult = await withRetry(() => selectModel(page, wantModel));
if (!modelResult?.ok) {
if (modelResult?.upgrade) {
throw new ArgumentError(
`${wantModel} model requires a paid Claude plan.`,
'Pick --model sonnet or --model haiku, or upgrade your account.',
);
}
throw new CommandExecutionError(`Could not switch to ${wantModel} model`);
}
// Post-toggle settle dropped — the next CDP eval (setAdaptiveThinking) gives
// React enough time to flush aria-checked updates between rountrips.
}
const thinkResult = await withRetry(() => setAdaptiveThinking(page, wantThink));
if (!thinkResult?.ok && wantThink) {
throw new CommandExecutionError('Could not enable Adaptive thinking');
}
// Post-toggle settle dropped — the next CDP eval (sendMessage / sendWithFile)
// gives React enough time to flush aria-checked updates.
if (kwargs.file) {View on GitHub (pinned to 49907e53dc)
Solutions
- Use --model sonnet or --model haiku which are available on free plans.
- Upgrade the Claude account to a paid plan that includes the requested model.
- Check the account's plan/workspace settings if a paid plan should include the model.
Example fix
// before opencli claude ask "hi" --model opus # free plan // after opencli claude ask "hi" --model haiku
Defensive patterns
Strategy: validation
Validate before calling
// Know your plan; default to free-tier models
const allowedModels = ['sonnet', 'haiku']; // free plan
if (opts.model && !allowedModels.includes(opts.model)) {
console.warn(`model ${opts.model} needs a paid plan; falling back`);
opts.model = 'sonnet';
} Try / catch
try {
await opencli.claude.ask(prompt, { model: 'opus' });
} catch (e) {
if (/requires a paid Claude plan/.test(e.message)) {
await opencli.claude.ask(prompt, { model: 'sonnet' });
} else throw e;
} Prevention
- Use sonnet/haiku unless you know the account has opus access.
- Verify plan entitlements before scripting premium models.
- Handle the upgrade hint programmatically by falling back to a cheaper model.
When it happens
Trigger: Passing --model opus (or another premium model) on a free Claude account; selectModel detects the plan-gated state and returns {ok:false, upgrade:true} after withRetry.
Common situations: Free-tier account selecting opus; workspace with restricted plan settings; enterprise account where the chosen model is not provisioned.
Related errors
- File could not be read: ${path}
- PAID_CONTENT
- Cannot switch to ${wantModel} model inside an existing conve
- Model name "${rawName}" is ambiguous.
- ${result.reason}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/29b8f56e0568cbfb.
Report an issue: GitHub.