affaan-m/ECC · error · ValueError
Unknown model: {model!r}. Allowed: {ALLOWED_MODELS}
Error message
Unknown model: {model!r}. Allowed: {ALLOWED_MODELS} What it means
run_scenario() validates the model argument against ALLOWED_MODELS = {'haiku','sonnet','opus'} before invoking claude -p. Any other string (including a full model ID like 'claude-3-5-sonnet-20241022', or a typo like 'Sonnet') is rejected up front.
Source
Thrown at skills/skill-comply/scripts/runner.py:44
SHELL_BUILTINS = frozenset({"cd", "pushd", "popd"})
@dataclass(frozen=True)
class ScenarioRun:
scenario: Scenario
observations: tuple[ObservationEvent, ...]
sandbox_dir: Path
def run_scenario(
scenario: Scenario,
model: str = "sonnet",
max_turns: int = 30,
timeout: int = 300,
) -> ScenarioRun:
"""Execute a scenario and extract tool calls from stream-json output."""
if model not in ALLOWED_MODELS:
raise ValueError(f"Unknown model: {model!r}. Allowed: {ALLOWED_MODELS}")
sandbox_dir = _safe_sandbox_dir(scenario.id)
_setup_sandbox(sandbox_dir, scenario)
result = subprocess.run(
[
"claude", "-p", scenario.prompt,
"--model", model,
"--max-turns", str(max_turns),
"--add-dir", str(sandbox_dir),
"--allowedTools", "Read,Write,Edit,Bash,Glob,Grep",
"--output-format", "stream-json",
"--verbose",
],
capture_output=True,
text=True,
timeout=timeout,
cwd=sandbox_dir,View on GitHub (pinned to 01e15490f0)
Solutions
- Pass one of the allowed short aliases: 'haiku', 'sonnet', or 'opus'.
- If you need a newer alias added, extend ALLOWED_MODELS in runner.py and document it.
- Do not pass full model IDs — claude -p resolves the alias itself.
Example fix
# before run = run_scenario(scenario, model='claude-3-5-sonnet-20241022') # after run = run_scenario(scenario, model='sonnet')
Defensive patterns
Strategy: validation
Validate before calling
from scripts.runner import ALLOWED_MODELS
def safe_model(model: str) -> str:
if model not in ALLOWED_MODELS:
raise SystemExit(f'Unknown model {model!r}; allowed: {sorted(ALLOWED_MODELS)}')
return model Type guard
from scripts.runner import ALLOWED_MODELS
def is_allowed_model(model: object) -> bool:
return isinstance(model, str) and model in ALLOWED_MODELS Try / catch
from scripts.runner import run_scenario
try:
run = run_scenario(scenario, model=user_model)
except ValueError as e:
if 'Unknown model' in str(e):
user_model = 'sonnet'
run = run_scenario(scenario, model=user_model)
else:
raise Prevention
- Restrict the model input in your CLI with argparse choices=sorted(ALLOWED_MODELS).
- Document the short-alias convention (haiku/sonnet/opus) wherever claude -p is invoked.
- Never accept arbitrary model strings from untrusted config — validate against the allowlist.
When it happens
Trigger: Passing model='claude-3-5-sonnet', model='Sonnet', model='gpt-4', or any alias not in the frozenset to run_scenario().
Common situations: Reusing a model identifier from another tool's config; passing a full Anthropic model ID where the CLI expects a short alias; copy-pasting a config that worked against a different harness.
Related errors
- claude -p failed (rc={result.returncode}): stderr={result.st
- Trace file not found: {path}
- Invalid JSON at line {i}: {e}
- Missing required field {e} at line {i}
- Spec file not found: {path}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/a56ed43a57ae17b9.
Report an issue: GitHub.