{"record":{"id":"f1343018a2d0ccfb","repo":"can1357/oh-my-pi","slug":"completion-could-not-resolve-a-model-for-the","errorCode":null,"errorMessage":"completion() could not resolve a model for the \"${finalTier}\" tier. Configure modelRoles.${finalTier === \"default\" ? \"default\" : finalTier} or ensure a provider is available.","messagePattern":"completion\\(\\) could not resolve a model for the \"(.+?)\" tier\\. Configure modelRoles\\.(.+?) or ensure a provider is available\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/completion-bridge.ts","lineNumber":121,"sourceCode":" * Run a single stateless completion on behalf of an eval cell's `completion()` call.\n * Returns a `{ text, details }` value shaped like a {@link callSessionTool}\n * result so the existing bridge transport carries it to either runtime.\n */\nexport async function runEvalCompletion(\n\targs: unknown,\n\toptions: EvalCompletionBridgeOptions,\n): Promise<EvalCompletionResult> {\n\tconst parsed = completionArgsSchema(args);\n\tif (parsed instanceof type.errors) {\n\t\tthrow new ToolError(`completion() received invalid arguments: ${parsed.summary}`);\n\t}\n\tconst { prompt, model: modelTier, system, schema } = parsed;\n\t// Apply default value for model if not provided\n\tconst finalTier: CompletionTier = modelTier ?? \"default\";\n\n\tconst model = resolveTierModel(finalTier, options.session);\n\tif (!model) {\n\t\tthrow new ToolError(\n\t\t\t`completion() could not resolve a model for the \"${finalTier}\" tier. Configure modelRoles.${finalTier === \"default\" ? \"default\" : finalTier} or ensure a provider is available.`,\n\t\t);\n\t}\n\n\tconst registry = options.session.modelRegistry;\n\tconst apiKey = await registry?.getApiKey(model);\n\tif (!registry || !apiKey) {\n\t\tthrow new ToolError(\n\t\t\t`completion() has no API key for ${formatModelString(model)}. Configure credentials for this provider or choose another tier.`,\n\t\t);\n\t}\n\n\tconst tools: Tool[] | undefined = schema\n\t\t? [\n\t\t\t\t{\n\t\t\t\t\tname: STRUCTURED_TOOL_NAME,\n\t\t\t\t\tdescription: \"Return your answer by calling this tool with the requested structured fields.\",\n\t\t\t\t\tparameters: schema,","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/completion-bridge.ts#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the missing role in config: add `modelRoles.default` (and `modelRoles.smol`/`modelRoles.slow` as needed) to your opencode/omp settings.","Verify at least one provider with credentials is configured so the registry has available models (the tier resolution returns undefined when `getAvailable()` is empty).","If the tier was passed explicitly in a cell, drop the `model` option to fall back to the session's active/default model.","Check for typos in the role pattern/model string in modelRoles; the resolver does exact string matching against available models."],"exampleFix":"// before (cell code, smol tier unconfigured)\nconst summary = await completion(\"summarize\", { model: \"smol\" });\n// after: configure roles, or fall back to default\nconst summary = await completion(\"summarize\");\n// config: { \"modelRoles\": { \"default\": \"anthropic/claude-...\", \"smol\": \"...\" } }","handlingStrategy":"validation","validationCode":"// resolve like the bridge does before calling completion()\nconst model = session.modelRegistry?.getAvailable().length\n  ? session.modelRegistry.getAvailable()[0]\n  : undefined;\nif (!model) throw new Error(\"No models configured: set modelRoles.default and provider credentials\");","typeGuard":null,"tryCatchPattern":"try {\n  const out = await completion(prompt, { model: \"smol\" });\n} catch (e) {\n  if (String(e).includes('could not resolve a model')) {\n    // fall back to default tier or surface a config error\n  } else throw e;\n}","preventionTips":["Always configure modelRoles.default, smol, and slow before running eval cells.","Verify provider credentials early so the registry has available models.","Prefer the default tier unless the smol/slow roles are explicitly configured."],"tags":["configuration","model-resolution","eval"],"backgroundTag":"model-role-not-configured","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}