can1357/oh-my-pi · error · Error
No API key for ${model.provider}
Error message
No API key for ${model.provider} What it means
After confirming a model is selected, generateDocument resolves its API key via modelRegistry.getApiKey(model, sessionId); if none resolves it throws. Like the model-switch guards, handoff refuses to run an LLM generation the session cannot authenticate, and this message reports only the provider name.
Source
Thrown at packages/coding-agent/src/session/session-handoff.ts:123
}
};
if (sourceSignal) {
sourceSignal.addEventListener("abort", onSourceAbort, { once: true });
if (sourceSignal.aborted) {
onSourceAbort();
}
}
try {
throwIfHandoffAborted(handoffSignal);
const model = this.#host.model();
if (!model) {
throw new Error("No model selected for handoff");
}
const apiKey = await this.#host.modelRegistry.getApiKey(model, this.#host.sessionId());
if (!apiKey) {
throw new Error(`No API key for ${model.provider}`);
}
// Build the handoff request through the SAME pipeline a live turn uses
// (`runEphemeralTurn` / `/btw` share it) so the oneshot reads the
// provider prompt cache the main turn populated instead of cold-missing
// the whole prefix: identical system prompt, normalized tools, and
// transform-/obfuscation-matched message history via
// `convertMessagesToLlm` + `buildSideRequestContext`, plus the live turn's
// effective provider cache key with a unique side `sessionId` so
// OpenAI/Codex append-only state never mixes with the live turn.
const cacheSessionId = this.#host.sessionId();
// The loop sends `promptCacheKey` (providerPromptCacheKey) and falls back to
// the provider session id; providers route on `promptCacheKey ?? sessionId`.
// Both can diverge from this.#host.sessionId() (tan/subagent/shared sessions), so
// mirror exactly what the live turn populated the cache under.
const handoffPromptCacheKey = this.#host.agent.promptCacheKey ?? this.#host.agent.sessionId;
const handoffPromptText = renderHandoffPrompt(this.#host.obfuscateTextForProvider(customInstructions));
const handoffSnapshot: AgentMessage[] = [View on GitHub (pinned to 9690622007)
Solutions
- Configure auth for the model's provider, then retry the handoff
- Switch to a model on an authenticated provider before compacting/handing off
- Pre-check getApiKey(model, sessionId) before starting handoff and fall back to another compaction method
- Verify env/config still holds the key if this previously worked
Example fix
// before await handoff.generateDocument(signal); // throws 'No API key for anthropic' // after const key = await registry.getApiKey(model, sessionId); if (!key) return fallbackCompaction(); await handoff.generateDocument(signal);
Defensive patterns
Strategy: validation
Validate before calling
const model = session.model();
if (!model) throw new Error("Select a model first");
const apiKey = await registry.getApiKey(model, session.sessionId());
if (!apiKey) throw new Error(`Configure auth for ${model.provider} before handoff`); Try / catch
try {
await handoff.generateDocument(signal);
} catch (err) {
if (err instanceof Error && err.message.startsWith("No API key for")) {
// configure provider auth or switch models, then retry
} else throw err;
} Prevention
- Verify getApiKey resolves before starting handoff/compaction
- Keep provider credentials configured and unexpired
- Offer model switching on auth failure instead of failing compaction
- Fall back to non-LLM compaction when no key is available
When it happens
Trigger: generateDocument called when the current session model's provider has no resolvable API key for this session.
Common situations: Handoff/compaction triggered after credentials were removed or expired; model set on a provider never configured; key resolution depends on session context that is absent.
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
- Devin auth error ${response.status} ${response.statusText}:
- Qwen token/API key is required
- OpenCode Go usage endpoint returned ${response.status}${deta
- Umans usage endpoint returned ${response.status} ${response.
- No API key for ${resolved.model.provider}/${resolved.model.i
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/13058bd4834ef58d.
Report an issue: GitHub.