{"record":{"id":"2a4c4dd7262055cf","repo":"can1357/oh-my-pi","slug":"model-must-be-provider-model-got-value","errorCode":null,"errorMessage":"Model must be provider/model, got ${value}","messagePattern":"Model must be provider/model, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/metaharness/src/tb/trial.ts","lineNumber":56,"sourceCode":"\nfunction addDelegatedUsage(messages: AgentMessage[], usage: TrialUsage): void {\n\tfor (const message of messages) {\n\t\tif (message.role !== \"toolResult\" || message.toolName !== \"inspect_image\" || !isRecord(message.details)) continue;\n\t\tconst delegated = message.details.usage;\n\t\tif (!isRecord(delegated)) continue;\n\t\tif (typeof delegated.input === \"number\") usage.input += delegated.input;\n\t\tif (typeof delegated.output === \"number\") usage.output += delegated.output;\n\t\tif (typeof delegated.cacheRead === \"number\") usage.cacheRead += delegated.cacheRead;\n\t\tif (typeof delegated.cacheWrite === \"number\") usage.cacheWrite += delegated.cacheWrite;\n\t\tif (isRecord(delegated.cost) && typeof delegated.cost.total === \"number\") {\n\t\t\tusage.costUsd += delegated.cost.total;\n\t\t}\n\t}\n}\n\nfunction modelParts(value: string): { provider: string; model: string } {\n\tconst slash = value.indexOf(\"/\");\n\tif (slash <= 0 || slash === value.length - 1) throw new Error(`Model must be provider/model, got ${value}`);\n\treturn { provider: value.slice(0, slash), model: value.slice(slash + 1) };\n}\n\n/** Run one Terminal-Bench task inside a fresh Vibemon microVM. */\nexport async function runTrial(opts: {\n\ttask: TbTask;\n\tmodel: string;\n\tbinaries: AgentBinaries;\n\tgateway: GatewayConfig;\n\tvmon: VmonConfig;\n\ttrialDir: string;\n\tlog?: (line: string) => void;\n}): Promise<TrialResult> {\n\tconst wallStartedAt = performance.now();\n\tconst deadlineMs = (opts.task.agentTimeoutSec + opts.task.verifierTimeoutSec + 900) * 1_000;\n\tlet vm: TrialVm | null = null;\n\tlet client: RpcClient | null = null;\n\tlet deadlineExpired = false;","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/metaharness/src/tb/trial.ts#L38-L74","documentation":"modelParts splits a model identifier on the first '/' into provider and model. A valid id must contain a slash that is neither the first nor last character; anything else (no slash, leading slash, trailing slash) is rejected with this message.","triggerScenarios":"runTrial/modelParts receives a --models entry like 'gpt-4o' (no provider), '/claude' (leading slash), or 'openai/' (trailing slash).","commonSituations":"Users accustomed to bare model names omit the provider prefix; YAML/config lists edited so a slash was dropped or duplicated; provider names like 'openai' forgotten for gateway routing.","solutions":["Format the model as provider/model, e.g. openai/gpt-4o or anthropic/claude-sonnet-4","Remove stray leading/trailing slashes from the model string","Check config files/env lists for truncated entries"],"exampleFix":"// before\ntb run --models gpt-4o\n// after\ntb run --models openai/gpt-4o","handlingStrategy":"validation","validationCode":"function assertModelId(v: string): void {\n  const i = v.indexOf(\"/\");\n  if (i <= 0 || i === v.length - 1) throw new Error(`Model must be provider/model, got ${v}`);\n}\nfor (const m of models) assertModelId(m);","typeGuard":"function isModelId(v: string): boolean {\n  const i = v.indexOf(\"/\");\n  return i > 0 && i < v.length - 1;\n}","tryCatchPattern":null,"preventionTips":["Always use provider/model form in configs and CLI flags","Lint config model lists with a provider/model regex","Avoid hand-edited lists; keep model strings next to provider names"],"tags":["validation","model-id","format"],"backgroundTag":"invalid-model-identifier","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}