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

  1. Pass one of the allowed short aliases: 'haiku', 'sonnet', or 'opus'.
  2. If you need a newer alias added, extend ALLOWED_MODELS in runner.py and document it.
  3. 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

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


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/a56ed43a57ae17b9. Report an issue: GitHub.