decolua/9router · error

Missing required field: url

Error message

Missing required field: url

What it means

The /v1 web-fetch endpoint requires a `url` field in the JSON body naming the page to extract. handleFetch reads body.url and returns HTTP 400 'Missing required field: url' when it is absent, null, empty, or not a string. This is an early input-validation gate before any URL parsing, SSRF checks, or provider dispatch.

Source

Thrown at src/sse/handlers/fetch.js:70

  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 (!providerInput || typeof providerInput !== "string") {
    log.warn("FETCH", "Missing provider/model");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: provider (or model)");
  }

  if (!targetUrl || typeof targetUrl !== "string") {
    log.warn("FETCH", "Missing url");
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: url");
  }

  // Validate URL format
  try {
    new URL(targetUrl);
  } catch {
    log.warn("FETCH", "Invalid URL", { url: targetUrl });
    return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid URL format");
  }

  // SSRF guard: reject internal/private/metadata targets
  try {
    assertPublicUrl(targetUrl);
  } catch (err) {
    log.warn("FETCH", "Blocked URL", { url: targetUrl });
    return errorResponse(HTTP_STATUS.BAD_REQUEST, err.message);
  }

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Add a string `url` field to the request body, e.g. {"model":"jina","url":"https://example.com"}
  2. If your URL is stored under another key, rename it to `url` before sending - there is no alias for this field
  3. Confirm the body is valid JSON with Content-Type: application/json so request.json() parses all fields

Example fix

// before
await fetch('/v1/fetch', { method: 'POST', body: JSON.stringify({ model: 'jina' }) });
// after
await fetch('/v1/fetch', { method: 'POST', body: JSON.stringify({ model: 'jina', url: 'https://example.com/page' }) });
Defensive patterns

Strategy: validation

Validate before calling

function validateFetchRequest(body) {
  if (!body || typeof body.url !== 'string' || body.url.length === 0) {
    throw new TypeError("request body must include a non-empty string 'url' field");
  }
  return body;
}

Type guard

function hasUrl(body) {
  return typeof body === 'object' && body !== null && typeof body.url === 'string' && body.url.length > 0;
}

Try / catch

try {
  const res = await fetch(endpoint, { method: 'POST', body: JSON.stringify(payload) });
  if (res.status === 400 && (await res.text()).includes('Missing required field: url')) {
    console.error('Payload missing url field:', payload);
  }
} catch (err) { /* network-level failure */ }

Prevention

When it happens

Trigger: POSTing to the fetch endpoint with a body that omits `url`, sets it to null/undefined, sends an empty string, or sends a non-string (number, object). Note the handler also accepts `provider` or `model` for the provider field, but `url` itself has no alias.

Common situations: Client forgot the url field; a UI bug sends only {model}; a wrapper script forwards a payload where the URL lives under a different key (link, target, href); JSON serialization dropped the field because it was undefined.

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