decolua/9router · error

Missing model

Error message

Missing model

What it means

The parsed request body has no 'model' field, which the gateway needs to resolve a provider or combo. After auth, handleChat checks body.model and returns 400 'Missing model' when it is undefined/empty.

Source

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

    log.debug("AUTH", "No API key provided (local mode)");
  }

  // Enforce API key if enabled in settings
  const settings = await getSettings();
  if (settings.requireApiKey) {
    if (!apiKey) {
      log.warn("AUTH", "Missing API key (requireApiKey=true)");
      return errorResponse(HTTP_STATUS.UNAUTHORIZED, "Missing API key");
    }
    const valid = await isValidApiKey(apiKey);
    if (!valid) {
      log.warn("AUTH", "Invalid API key (requireApiKey=true)");
      return errorResponse(HTTP_STATUS.UNAUTHORIZED, "Invalid API key");
    }
  }

  if (!modelStr) {
    log.warn("CHAT", "Missing model");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing model");
  }

  // Bypass naming/warmup requests before combo rotation to avoid wasting rotation slots
  const userAgent = request?.headers?.get("user-agent") || "";
  const bypassResponse = handleBypassRequest(body, modelStr, userAgent, !!settings.ccFilterNaming);
  if (bypassResponse) return bypassResponse.response || bypassResponse;

  const requiredCapabilities = detectRequiredCapabilities(body);

  // Check if model is a combo (has multiple models with fallback)
  const comboModels = await getComboModels(modelStr);
  if (comboModels) {
    // Check for combo-specific strategy first, fallback to global
    const comboStrategies = settings.comboStrategies || {};
    const comboSpecificStrategy = comboStrategies[modelStr]?.fallbackStrategy;
    const comboStrategy = comboSpecificStrategy || settings.comboStrategy || "fallback";
    const augmentedModels = augmentModelsWithCapacityAdapter(comboModels, requiredCapabilities, settings);

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Add the model field: {"model":"<provider/model or combo name>", "messages":[...]}.
  2. Log the outgoing payload before sending and confirm model is a non-empty string.
  3. Use a model name listed in the 9Router dashboard (provider/model or a configured combo).
  4. If middleware rewrites the body, ensure it preserves the model field.

Example fix

// before
await client.chat.create({ messages });

// after
await client.chat.create({ model: 'openai/gpt-4o', messages });
Defensive patterns

Strategy: validation

Validate before calling

if (!body || typeof body.model !== 'string' || !body.model.trim()) {
  throw new TypeError("chat request requires a non-empty 'model' field");
}

Type guard

function hasModel(body) {
  return Boolean(body) && typeof body === 'object' &&
    typeof body.model === 'string' && body.model.trim().length > 0;
}

Try / catch

const res = await fetch(url, opts);
if (res.status === 400 && (await res.text()).includes('Missing model')) {
  throw new Error('Request payload is missing body.model');
}

Prevention

When it happens

Trigger: POST to /v1/chat/completions with JSON that lacks body.model, e.g. {"messages":[...]} or {"model":"","messages":[...]}.

Common situations: Hand-written payloads or scripts that build the request object and forget the model; clients where the model parameter is set conditionally; requests forwarded through middleware that strips unknown fields; using an embeddings-style payload shape for chat.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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