Skip to content

droid exec --model rejects all custom model IDs (BYOK) #787

@mikez93

Description

@mikez93

Summary

droid exec --model <custom-model-id> rejects all custom model IDs with "Invalid model" even though they are listed as available in the error output. Only the current session default custom model works via --model. Built-in model IDs route through Factory's API (returning 402 for non-subscribers) instead of the user's BYOK proxy.

Environment

  • Droid CLI version: 0.70.0, 0.74.0 (tested both)
  • OS: macOS (Darwin 23.6.0, arm64)
  • Custom models: Configured in ~/.factory/settings.json with BYOK proxy at localhost

Steps to Reproduce

  1. Configure custom models in ~/.factory/settings.json (e.g., Gemini Flash via OpenAI-compatible proxy)
  2. Run: droid exec --auto low --model "custom:Gemini-3-Flash-Low-[Proxy]-18" "Say hello"
  3. Observe: "Invalid model" error, even though "Gemini 3 Flash Low [Proxy]" is listed under "Available custom models"

Tested formats that all fail:

  • custom:Gemini-3-Flash-Low-[Proxy]-18 (the id field from settings.json)
  • Gemini 3 Flash Low [Proxy] (the displayName from settings.json)
  • custom:Claude-Haiku-4.5-Medium-Thinking-6 (non-default Claude custom model)

The only custom model that works is the one set as sessionDefaultSettings.model — which is effectively a no-op since it's already the default.

Built-in model IDs (e.g., claude-haiku-4-5-20251001) are accepted syntactically but fail with 402 Payment Required because they route through Factory's API instead of the BYOK proxy.

Expected Behavior

--model should accept any custom model ID from ~/.factory/settings.json and route through the configured BYOK endpoint, not just the current session default.

Impact

This blocks headless droid exec workflows that need to select specific models programmatically (e.g., using a cheap model for batch enrichment pipelines while keeping an expensive model as the interactive default).

Workaround

Omit the --model flag entirely and rely on the session default. This means you can't select different models for different use cases without manually changing sessionDefaultSettings.model between runs.

Log Evidence

From ~/.factory/logs/droid-log-single.log:

MetaError: Invalid model: custom:Gemini-3-Flash-Low-[Proxy]-18
    at syR (src/commands/assertValidOptions.ts:83:17)
    at async <anonymous> (src/commands/exec.ts:957:21)

The validation in assertValidOptions.ts lists custom models but fails to match against them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions