can1357/oh-my-pi · error · Error

No API key for ${model.provider}/${model.id}

Error message

No API key for ${model.provider}/${model.id}

What it means

After resolving a tiny/smol model, aiStage verifies that an API key is available for the model's provider via registry.getApiKey. If none is found, it throws with the provider/model id so the user knows exactly which credential is missing. This fails fast before making the request.

Source

Thrown at packages/coding-agent/src/cli/git-tui/ai-stage.ts:89

 * @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 are
		// picked as a coherent set instead of N independent coin flips.

View on GitHub (pinned to 9690622007)

Solutions

  1. Authenticate with the provider (e.g. run the provider login/API-key setup for omp).
  2. Set the provider's API key environment variable in the shell/CI environment.
  3. Re-point the tiny/smol role at a provider you do have credentials for.

Example fix

// before
export PATH=... // no key
// after
export ANTHROPIC_API_KEY=sk-ant-...
Defensive patterns

Strategy: validation

Validate before calling

const model = resolveRoleSelection(["tiny", "smol"], settings, registry.getAvailable())?.model;
if (model && !(await registry.getApiKey(model))) {
  throw new Error(`Run provider auth for ${model.provider} before AI staging`);
}

Try / catch

try {
  await aiStage(opts);
} catch (e) {
  if (e instanceof Error && e.message.startsWith("No API key for")) {
    console.error("Authenticate the provider first:", e.message);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: A tiny/smol role model resolves from the registry (e.g. anthropic/claude-3-5-haiku) but no API key is stored for that provider in the auth storage (env var absent, no credentials file).

Common situations: New machine without provider login, expired/removed credentials, CI environments lacking the provider's API key environment variable, or role pointing at a provider never authenticated.

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/0c2b922d41345c72. Report an issue: GitHub.