{"record":{"id":"c0d143852b9a5ca5","repo":"can1357/oh-my-pi","slug":"at-least-one-model-is-required","errorCode":null,"errorMessage":"at least one --model is required","messagePattern":"at least one --model is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/metaharness/src/tb/cli.ts","lineNumber":201,"sourceCode":"\t\t\t\tconfig.vmonUrl = take();\n\t\t\t\tbreak;\n\t\t\tcase \"--vmon-token\":\n\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 {","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/metaharness/src/tb/cli.ts#L183-L219","documentation":"After option parsing, parseArgs enforces that at least one model was supplied via -m/--model (repeatable). An empty models array (and no --help) throws this error.","triggerScenarios":"Running `tb` (or with only non-model flags like --attempts 3) without any -m/--model occurrence.","commonSituations":"First-time users omitting the required flag; scripts where a MODELS variable was empty so the -m flags were never emitted; confusing --model with a positional argument and passing 'x/y' bare.","solutions":["Add at least one --model provider/model flag","Repeat -m/--model for each model to test","Pass bare model names positionally? No — use the flag; positionals are not accepted for models"],"exampleFix":"// before\n$ tb --attempts 2\n// after\n$ tb --attempts 2 --model anthropic/claude-sonnet-4","handlingStrategy":"validation","validationCode":"if (!process.argv.slice(2).some(a => a === \"-m\" || a === \"--model\" || a.startsWith(\"--model=\"))) {\n  throw new Error(\"tb requires at least one --model provider/model\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  config = parseArgs(args);\n} catch (err) {\n  if (String(err.message).includes(\"--model is required\")) {\n    console.error(\"usage: tb -m <provider/model> [-m <provider/model> ...]\");\n    process.exit(2);\n  }\n  throw err;\n}","preventionTips":["Always include -m in wrapper scripts; guard empty MODELS variables","Model is a flag, not a positional — never pass it bare","Print usage when arg count is below a minimum"],"tags":["cli","validation","arguments"],"backgroundTag":"missing-required-argument","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}