can1357/oh-my-pi · error · ToolError

completion() could not resolve a model for the "${finalTier}

Error message

completion() could not resolve a model for the "${finalTier}" tier. Configure modelRoles.${finalTier === "default" ? "default" : finalTier} or ensure a provider is available.

What it means

The eval `completion()` bridge resolves the requested tier ("smol", "default", or "slow") to a concrete model via the session's model registry. This ToolError is thrown by `runEvalCompletion` when `resolveTierModel` returns undefined — no model in the registry matches the tier's role pattern (e.g. `@smol`, `@default`) and, for the default tier, no active session model exists either. It indicates configuration/environment state, not a runtime request failure.

Source

Thrown at packages/coding-agent/src/eval/completion-bridge.ts:121

 * Run a single stateless completion on behalf of an eval cell's `completion()` call.
 * Returns a `{ text, details }` value shaped like a {@link callSessionTool}
 * result so the existing bridge transport carries it to either runtime.
 */
export async function runEvalCompletion(
	args: unknown,
	options: EvalCompletionBridgeOptions,
): Promise<EvalCompletionResult> {
	const parsed = completionArgsSchema(args);
	if (parsed instanceof type.errors) {
		throw new ToolError(`completion() received invalid arguments: ${parsed.summary}`);
	}
	const { prompt, model: modelTier, system, schema } = parsed;
	// Apply default value for model if not provided
	const finalTier: CompletionTier = modelTier ?? "default";

	const model = resolveTierModel(finalTier, options.session);
	if (!model) {
		throw new ToolError(
			`completion() could not resolve a model for the "${finalTier}" tier. Configure modelRoles.${finalTier === "default" ? "default" : finalTier} or ensure a provider is available.`,
		);
	}

	const registry = options.session.modelRegistry;
	const apiKey = await registry?.getApiKey(model);
	if (!registry || !apiKey) {
		throw new ToolError(
			`completion() has no API key for ${formatModelString(model)}. Configure credentials for this provider or choose another tier.`,
		);
	}

	const tools: Tool[] | undefined = schema
		? [
				{
					name: STRUCTURED_TOOL_NAME,
					description: "Return your answer by calling this tool with the requested structured fields.",
					parameters: schema,

View on GitHub (pinned to 9690622007)

Solutions

  1. Set the missing role in config: add `modelRoles.default` (and `modelRoles.smol`/`modelRoles.slow` as needed) to your opencode/omp settings.
  2. Verify at least one provider with credentials is configured so the registry has available models (the tier resolution returns undefined when `getAvailable()` is empty).
  3. If the tier was passed explicitly in a cell, drop the `model` option to fall back to the session's active/default model.
  4. Check for typos in the role pattern/model string in modelRoles; the resolver does exact string matching against available models.

Example fix

// before (cell code, smol tier unconfigured)
const summary = await completion("summarize", { model: "smol" });
// after: configure roles, or fall back to default
const summary = await completion("summarize");
// config: { "modelRoles": { "default": "anthropic/claude-...", "smol": "..." } }
Defensive patterns

Strategy: validation

Validate before calling

// resolve like the bridge does before calling completion()
const model = session.modelRegistry?.getAvailable().length
  ? session.modelRegistry.getAvailable()[0]
  : undefined;
if (!model) throw new Error("No models configured: set modelRoles.default and provider credentials");

Try / catch

try {
  const out = await completion(prompt, { model: "smol" });
} catch (e) {
  if (String(e).includes('could not resolve a model')) {
    // fall back to default tier or surface a config error
  } else throw e;
}

Prevention

When it happens

Trigger: Cell code calls `completion(prompt)` or `completion(prompt, { model: "smol" })` while the session's model registry has no available models, no model is configured for the `modelRoles.default`/`smol`/`slow` role, or the role pattern does not match any available model.

Common situations: Fresh eval environment with no providers configured or no API keys set (so `getAvailable()` is empty); a config that defines `modelRoles.default` but not `modelRoles.smol` while a cell requests the smol tier; a typo'd or renamed model id in modelRoles; running evals in CI without the user's provider config.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f1343018a2d0ccfb. Report an issue: GitHub.