can1357/oh-my-pi · error · Error
No tiny/smol model available for AI staging
Error message
No tiny/smol model available for AI staging
What it means
aiStage routes its diff-grouping request through a lightweight model; it resolves the configured "tiny" or "smol" role selection from settings against the registry's available models. If no model fills either role, it throws instead of silently failing later during completion.
Source
Thrown at packages/coding-agent/src/cli/git-tui/ai-stage.ts:88
* stage the matching hunks. Called by the git TUI's unstaged-header wand pill.
* @throws when no model/key resolves, git fails, or every judgement in a pass errors.
*/
export async function aiStage(options: AiStageOptions): Promise<AiStageOutcome> {
const { cwd, instruction, signal, onProgress } = options;
const repo = vcs.requireGit(cwd);
const untracked = options.files.filter(file => file.kind === "untracked");
const tracked = options.files.filter(file => file.kind !== "untracked" && file.kind !== "conflicted");
if (tracked.length === 0 && untracked.length === 0) throw new Error("No unstaged changes to filter");
onProgress?.("Resolving model…");
const settings = await Settings.init({ cwd });
const authStorage = await discoverAuthStorage();
try {
const registry = new ModelRegistry(authStorage);
await registry.refresh();
await loadCliExtensionProviders(registry, settings, cwd);
const model = resolveRoleSelection(["tiny", "smol"], settings, registry.getAvailable())?.model;
if (!model) throw new Error("No tiny/smol model available for AI staging");
if (!(await registry.getApiKey(model))) throw new Error(`No API key for ${model.provider}/${model.id}`);
const complete = createCompleter(model, registry.resolver(model), signal);
const rawDiff = tracked.length > 0 ? await repo.diffText({ files: tracked.map(file => file.path) }, signal) : "";
const fileDiffs = new Map(parseFileDiffs(rawDiff).map(entry => [entry.filename, entry]));
interface Candidate {
file: Pick<ChangedFile, "path" | "kind">;
/** Parsed worktree diff; absent for untracked files. */
diff?: FileDiff;
}
const candidates: Candidate[] = tracked.flatMap(file => {
const diff = fileDiffs.get(file.path);
return diff ? [{ file, diff }] : [];
});
candidates.push(...untracked.map(file => ({ file })));
// File pass: one completion sees the whole (batched) list, so files areView on GitHub (pinned to 9690622007)
Solutions
- Configure a tiny or smol model in settings (role selection) for AI staging.
- Ensure a model catalog/provider is configured so the registry has available models.
- Check provider exclude/filters in settings that may be hiding eligible models.
Example fix
// before (settings)
{}
// after (settings)
{ "roles": { "smol": "anthropic/claude-3-5-haiku" } } Defensive patterns
Strategy: validation
Validate before calling
const settings = await Settings.init({ cwd });
const registry = new ModelRegistry(await discoverAuthStorage());
await registry.refresh();
const hasModel = !!resolveRoleSelection(["tiny", "smol"], settings, registry.getAvailable())?.model;
if (!hasModel) { /* fall back to manual staging or configure a model */ } Try / catch
try {
await aiStage(opts);
} catch (e) {
if (e instanceof Error && e.message.includes("No tiny/smol model available")) {
await manualStage(); // fallback path
return;
}
throw e;
} Prevention
- Configure a tiny/smol role model in settings during setup.
- Verify with a settings/registry check before offering AI-staging features in tooling.
- Avoid provider exclude filters that eliminate all small models.
When it happens
Trigger: Calling aiStage when settings define no tiny/smol role model and no available model in the registry matches the tiny or smol role.
Common situations: Fresh installs with default/empty settings, models.json filtered down by provider excludes, or an environment where all candidate models were disabled.
Related errors
- No model available for commit generation
- Security scan preflight requires an active model
- No model configured
- Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL
- Cannot register custom API "${api}": built-in API names are
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/85af0483c9ba2b21.
Report an issue: GitHub.