{"record":{"id":"264e789435edc7e4","repo":"decolua/9router","slug":"missing-required-field-provider-or-model","errorCode":null,"errorMessage":"Missing required field: provider (or model)","messagePattern":"Missing required field: provider \\(or model\\)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"src/sse/handlers/fetch.js","lineNumber":65,"sourceCode":"    log.debug(\"AUTH\", \"No API key provided (local mode)\");\n  }\n\n  // Enforce API key if enabled in settings\n  const settings = await getSettings();\n  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 (!providerInput || typeof providerInput !== \"string\") {\n    log.warn(\"FETCH\", \"Missing provider/model\");\n    return errorResponse(HTTP_STATUS.BAD_REQUEST, \"Missing required field: provider (or model)\");\n  }\n\n  if (!targetUrl || typeof targetUrl !== \"string\") {\n    log.warn(\"FETCH\", \"Missing url\");\n    return errorResponse(HTTP_STATUS.BAD_REQUEST, \"Missing required field: url\");\n  }\n\n  // Validate URL format\n  try {\n    new URL(targetUrl);\n  } catch {\n    log.warn(\"FETCH\", \"Invalid URL\", { url: targetUrl });\n    return errorResponse(HTTP_STATUS.BAD_REQUEST, \"Invalid URL format\");\n  }\n\n  // SSRF guard: reject internal/private/metadata targets\n  try {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/sse/handlers/fetch.js#L47-L83","documentation":"HTTP 400 returned by handleFetch when neither `provider` nor `model` is present (or not a string) in the JSON body. The fetch endpoint routes by provider id (which doubles as the model for webFetch), accepting either field name, but requires one of them.","triggerScenarios":"POST to the fetch endpoint with a body like {\"url\":\"https://example.com\"} or {\"provider\":123}, or with the provider under a misspelled key (\"provide\", \"service\").","commonSituations":"Copied a curl example and dropped a field; SDK builds body from options where the provider option name differs; passing a non-string (object/null) provider value.","solutions":["Add `provider` (or `model`) as a string in the body, e.g. \"jina\" or the provider id from the dashboard","Validate the payload shape client-side before sending","Check field spelling — only `provider` and `model` are accepted"],"exampleFix":"// before\n{ url: 'https://example.com' }\n// after\n{ provider: 'jina', url: 'https://example.com' }","handlingStrategy":"validation","validationCode":"function assertFetchPayload(body) {\n  const p = body?.provider ?? body?.model;\n  if (typeof p !== 'string' || !p.trim()) throw new Error('fetch payload requires string `provider` (or `model`)');\n  if (typeof body?.url !== 'string') throw new Error('fetch payload requires string `url`');\n}","typeGuard":"function hasProvider(body) {\n  const p = body?.provider ?? body?.model;\n  return typeof p === 'string' && p.trim().length > 0;\n}","tryCatchPattern":"const res = await post('/v1/fetch', payload);\nif (res.status === 400 && (await res.text()).includes('provider (or model)')) {\n  console.error('Add `provider` or `model` to the fetch payload');\n}","preventionTips":["Use one payload-builder helper for fetch requests","Keep the accepted field names (`provider`/`model`) documented in your API client","Add a schema check (zod/ajv) on the payload in tests"],"tags":["validation","bad-request","missing-field"],"backgroundTag":"missing-required-field","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}