{"record":{"id":"a7e4d02b5a65fa9f","repo":"decolua/9router","slug":"missing-required-field-input","errorCode":null,"errorMessage":"Missing required field: input","messagePattern":"Missing required field: input","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"src/sse/handlers/embeddings.js","lineNumber":74,"sourceCode":"  if (settings.requireApiKey) {\n    if (!apiKey) {\n      log.warn(\"AUTH\", \"Missing API key (requireApiKey=true)\");\n      return errorResponse(HTTP_STATUS.UNAUTHORIZED, \"Missing API key\");\n    }\n    const valid = await isValidApiKey(apiKey);\n    if (!valid) {\n      log.warn(\"AUTH\", \"Invalid API key (requireApiKey=true)\");\n      return errorResponse(HTTP_STATUS.UNAUTHORIZED, \"Invalid API key\");\n    }\n  }\n\n  if (!modelStr) {\n    log.warn(\"EMBEDDINGS\", \"Missing model\");\n    return errorResponse(HTTP_STATUS.BAD_REQUEST, \"Missing model\");\n  }\n\n  if (!body.input) {\n    log.warn(\"EMBEDDINGS\", \"Missing input\");\n    return errorResponse(HTTP_STATUS.BAD_REQUEST, \"Missing required field: input\");\n  }\n\n  const modelInfo = await getModelInfo(modelStr);\n  if (!modelInfo.provider) {\n    log.warn(\"EMBEDDINGS\", \"Invalid model format\", { model: modelStr });\n    return errorResponse(HTTP_STATUS.BAD_REQUEST, \"Invalid model format\");\n  }\n\n  const { provider, model } = modelInfo;\n\n  if (modelStr !== `${provider}/${model}`) {\n    log.info(\"ROUTING\", `${modelStr} → ${provider}/${model}`);\n  } else {\n    log.info(\"ROUTING\", `Provider: ${provider}, Model: ${model}`);\n  }\n\n  // Credential + fallback loop (mirrors handleChat)","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/sse/handlers/embeddings.js#L56-L92","documentation":"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.","triggerScenarios":"POST to the embeddings endpoint with a body containing `model` but no `input`, an empty string input, or an empty input array.","commonSituations":"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.","solutions":["Add a non-empty `input` field (string or array of strings) to the request body","Guard client-side: filter out empty documents and bail early if nothing remains","Verify the field name is exactly `input` per the OpenAI-compatible schema"],"exampleFix":"// before\nconst docs = items.map(i => i.text).filter(Boolean); // may be []\nawait embed({ model, input: docs });\n// after\nconst docs = items.map(i => i.text).filter(Boolean);\nif (!docs.length) throw new Error('No documents to embed');\nawait embed({ model, input: docs });","handlingStrategy":"validation","validationCode":"const input = docs.map(d => d.text).filter(t => typeof t === 'string' && t.trim());\nif (input.length === 0) throw new Error('Nothing to embed: input is empty');\nconst payload = { model, input };","typeGuard":"function hasInput(body) {\n  if (typeof body?.input === 'string') return body.input.trim().length > 0;\n  if (Array.isArray(body?.input)) return body.input.length > 0;\n  return false;\n}","tryCatchPattern":"if (res.status === 400 && (await res.text()).includes('field: input')) {\n  console.error('Request had empty/missing `input` — check document filtering logic');\n}","preventionTips":["Filter empty documents before batching and check the batch is non-empty","Use the exact field name `input` per OpenAI-compatible schema","Log payload shape (keys only) before sending in debug mode"],"tags":["validation","bad-request","embeddings"],"backgroundTag":"missing-required-field","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}