{"record":{"id":"53f0e3d6fe96a674","repo":"can1357/oh-my-pi","slug":"invalid-model-model-expected-provider-model","errorCode":null,"errorMessage":"invalid model ${model}; expected provider/model","messagePattern":"invalid model (.+?); expected provider/model","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/metaharness/src/tb/cli.ts","lineNumber":204,"sourceCode":"\t\t\t\tconfig.vmonToken = take();\n\t\t\t\tbreak;\n\t\t\tcase \"--list\":\n\t\t\t\tconfig.list = true;\n\t\t\t\tbreak;\n\t\t\tcase \"-h\":\n\t\t\tcase \"--help\":\n\t\t\t\tconfig.help = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`unknown option: ${arg}`);\n\t\t}\n\t}\n\n\tif (config.help) return config;\n\tif (config.models.length === 0) throw new Error(\"at least one --model is required\");\n\tfor (const model of config.models) {\n\t\tconst slash = model.indexOf(\"/\");\n\t\tif (slash <= 0 || slash === model.length - 1) throw new Error(`invalid model ${model}; expected provider/model`);\n\t}\n\tfor (const [flag, value] of [\n\t\t[\"--attempts\", config.attempts],\n\t\t[\"--concurrency\", config.concurrency],\n\t\t[\"--epochs\", config.epochs],\n\t] as const) {\n\t\tif (!Number.isInteger(value) || value < 1) throw new Error(`${flag} must be a positive integer`);\n\t}\n\tif (config.budget !== null && (!Number.isFinite(config.budget) || config.budget < 0)) {\n\t\tthrow new Error(\"--budget must be a non-negative number\");\n\t}\n\treturn config;\n}\n\nclass Semaphore {\n\t#available: number;\n\t#queue: Array<() => void> = [];\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/metaharness/src/tb/cli.ts#L186-L222","documentation":"Each --model value must be of the form provider/model: it must contain a '/' that is neither the first character nor the last. This error is thrown for values violating that shape.","triggerScenarios":"Passing a bare model name ('claude-sonnet-4'), a leading-slash ('/gpt-4o'), a trailing slash ('openrouter/'), or an empty string via --model=.","commonSituations":"Model IDs from docs that omit the provider prefix; joining a list where the last element is empty; Windows-style paths or typos introducing stray slashes; using an OpenRouter variant-only suffix instead of the full id.","solutions":["Use full provider/model form, e.g. anthropic/claude-sonnet-4","Remove leading/trailing slashes from the value","Check for empty values caused by unquoted shell variables"],"exampleFix":"// before\n$ tb --model claude-sonnet-4\n// after\n$ tb --model anthropic/claude-sonnet-4","handlingStrategy":"validation","validationCode":"const validModel = (m: string) => {\n  const s = m.indexOf(\"/\");\n  return s > 0 && s < m.length - 1;\n};\nif (!models.every(validModel)) throw new Error(\"every model must be provider/model\");","typeGuard":null,"tryCatchPattern":"try {\n  config = parseArgs(args);\n} catch (err) {\n  if (String(err.message).startsWith(\"invalid model\")) {\n    console.error(`${err.message} — use e.g. anthropic/claude-sonnet-4`);\n    process.exit(2);\n  }\n  throw err;\n}","preventionTips":["Always prefix bare model names with their provider id","Trim model strings from env/config before passing","Validate model lists at script boundaries"],"tags":["cli","validation","model-id"],"backgroundTag":"invalid-model-id-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}