decolua/9router · error

Invalid model format

Error message

Invalid model format

What it means

handleSingleModelChat resolved the requested model string via getModelInfo and got back no provider/model pair, meaning the string matches neither a registered provider/model nor a known combo. The handler returns 400 'Invalid model format'.

Source

Thrown at src/sse/handlers/chat.js:212

        });
      }

      const comboStickyLimit = chatSettings.comboStickyRoundRobinLimit;
      log.info("CHAT", `Combo "${modelStr}" with ${augmentedModels.length} models (strategy: ${comboStrategy}, sticky: ${comboStickyLimit})`);
      return handleComboChat({
        body,
        models: augmentedModels,
        handleSingleModel: withCapacityAdapterStripping(
          (b, m) => handleSingleModelChat(b, m, clientRawRequest, request, apiKey),
          adapterAdded
        ),
        log,
        comboName: modelStr,
        comboStrategy,
        comboStickyLimit
      });
    }
    log.warn("CHAT", "Invalid model format", { model: modelStr });
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid model format");
  }

  const { provider, model } = modelInfo;

  // Routing shown in the unified "▶" line (client model → provider/model)

  // Extract userAgent from request
  const userAgent = request?.headers?.get("user-agent") || "";

  // Try with available accounts (fallback on errors)
  const excludeConnectionIds = new Set();
  let lastError = null;
  let lastStatus = null;

  while (true) {
    const credentials = await getProviderCredentials(provider, excludeConnectionIds, model);

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Check the 9Router dashboard's model list and use an exact registered model string (provider/model).
  2. Fix typos and separators — the format must match what getModelInfo expects (provider/model or a combo name).
  3. If the provider's model was renamed/added, update open-sse/config/providerModels.js or the provider registry, then restart.
  4. If it should be a combo, recreate the combo in the dashboard with that name.

Example fix

// before
{ "model": "GPT-4o-mini" }

// after
{ "model": "openai/gpt-4o-mini" }
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = new Set(['openai/gpt-4o', 'openai/gpt-4o-mini' /* fetch full list from dashboard API */]);
if (!KNOWN.has(model)) throw new Error(`unknown model: ${model} — must be provider/model or a combo name`);

Type guard

function isProviderModel(s) {
  return typeof s === 'string' && /^[a-z0-9_-]+\/[\w.:-]+$/i.test(s);
}

Try / catch

const res = await fetch(url, opts);
if (res.status === 400 && (await res.text()).includes('Invalid model format')) {
  throw new Error(`Model "${opts.body.model}" is not registered in 9Router`);
}

Prevention

When it happens

Trigger: POST /v1/chat/completions with model set to something that getModelInfo cannot parse: an unknown 'provider/model' prefix, a typo'd model name, or a model not present in the provider registry/config.

Common situations: Model name copied from upstream docs that 9Router doesn't register; renamed model after a provider updated their catalog; combo deleted in dashboard but still referenced by the client; wrong separator (e.g. 'openai:gpt-4o' instead of 'openai/gpt-4o'); client still pointing at a model from a previous router config.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/7f90666aa89fe54a. Report an issue: GitHub.