decolua/9router · error

Missing required field: input

Error message

Missing required field: input

What it means

HTTP 400 returned by handleEmbeddings when `body.input` is missing, empty, or falsy. OpenAI-style embeddings endpoints require at least one text to embed; the handler rejects the request before contacting any provider.

Source

Thrown at src/sse/handlers/embeddings.js:74

  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("EMBEDDINGS", "Missing model");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing model");
  }

  if (!body.input) {
    log.warn("EMBEDDINGS", "Missing input");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: input");
  }

  const modelInfo = await getModelInfo(modelStr);
  if (!modelInfo.provider) {
    log.warn("EMBEDDINGS", "Invalid model format", { model: modelStr });
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid model format");
  }

  const { provider, model } = modelInfo;

  if (modelStr !== `${provider}/${model}`) {
    log.info("ROUTING", `${modelStr} → ${provider}/${model}`);
  } else {
    log.info("ROUTING", `Provider: ${provider}, Model: ${model}`);
  }

  // Credential + fallback loop (mirrors handleChat)

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Add a non-empty `input` field (string or array of strings) to the request body
  2. Guard client-side: filter out empty documents and bail early if nothing remains
  3. Verify the field name is exactly `input` per the OpenAI-compatible schema

Example fix

// before
const docs = items.map(i => i.text).filter(Boolean); // may be []
await embed({ model, input: docs });
// after
const docs = items.map(i => i.text).filter(Boolean);
if (!docs.length) throw new Error('No documents to embed');
await embed({ model, input: docs });
Defensive patterns

Strategy: validation

Validate before calling

const input = docs.map(d => d.text).filter(t => typeof t === 'string' && t.trim());
if (input.length === 0) throw new Error('Nothing to embed: input is empty');
const payload = { model, input };

Type guard

function hasInput(body) {
  if (typeof body?.input === 'string') return body.input.trim().length > 0;
  if (Array.isArray(body?.input)) return body.input.length > 0;
  return false;
}

Try / catch

if (res.status === 400 && (await res.text()).includes('field: input')) {
  console.error('Request had empty/missing `input` — check document filtering logic');
}

Prevention

When it happens

Trigger: POST to the embeddings endpoint with a body containing `model` but no `input`, an empty string input, or an empty input array.

Common situations: Passing an empty array after filtering documents; wrong field name (e.g. `texts` or `prompt`) instead of `input`; template literal that evaluated to empty string.

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/a7e4d02b5a65fa9f. Report an issue: GitHub.