payloadcms/payload · error · APIError

A valid URL string is required.

Error message

A valid URL string is required.

What it means

APIError (HTTP 400, 'A valid URL string is required.') thrown when the `src` query parameter is missing (null) or not a string. The handler reads searchParams.get('src') and requires a truthy string before attempting URL parsing.

Source

Thrown at packages/payload/src/uploads/endpoints/getFileFromURL.ts:52

      throw new Forbidden(req.t)
    }
  } else {
    // creating doc
    const accessResult = await executeAccess({ slug: config.slug, req }, config.access?.create)
    if (!accessResult) {
      throw new Forbidden(req.t)
    }
  }

  if (!req.url) {
    throw new APIError('Request URL is missing.', 400)
  }

  const { searchParams } = new URL(req.url)
  const src = searchParams.get('src')

  if (!src || typeof src !== 'string') {
    throw new APIError('A valid URL string is required.', 400)
  }

  const hasAllowList =
    typeof config.upload.pasteURL === 'object' && Array.isArray(config.upload.pasteURL.allowList)

  let fileURL: string
  try {
    fileURL = new URL(src).href
  } catch {
    throw new APIError('A valid URL string is required.', 400)
  }

  if (hasAllowList && !isURLAllowed(fileURL, config.upload.pasteURL.allowList)) {
    throw new APIError('The provided URL is not allowed.', 400)
  }

  let redirectCount = 0
  const maxRedirects = 3

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Always include a non-empty ?src=<absolute-url> in the request.
  2. Validate on the client that the URL input is non-empty before issuing the request.
  3. URL-encode the src value to preserve query/embedded chars.
  4. If src must be optional in your flow, fork the endpoint or pre-validate upstream.

Example fix

// before
fetch(`/api/media/paste-url`, { method: 'POST' })
// after — include src
fetch(`/api/media/paste-url?src=${encodeURIComponent(src)}`, {
  method: 'POST', headers: { Authorization: `JWT ${token}` },
})
Defensive patterns

Strategy: validation

Validate before calling

function hasSrcParam(url: string): boolean {
  try { return Boolean(new URL(url, 'http://x').searchParams.get('src')) } catch { return false }
}
if (!hasSrcParam(myUrl)) throw new Error('Add ?src=<url>')

Type guard

const hasNonEmptySrc = (search: URLSearchParams): boolean =>
  typeof search.get('src') === 'string' && (search.get('src') as string).length > 0

Try / catch

try {
  await fetch(`/api/media/paste-url?src=${encodeURIComponent(src)}`, { method: 'POST' })
} catch (e) {
  if (/A valid URL string is required/.test(e.message)) alert('Provide a source URL')
}

Prevention

When it happens

Trigger: Calling /api/:collection/paste-url without a ?src= query param, with an empty ?src=, or where the param is somehow not a string (array via repeated keys). Triggered after auth and pasteURL-enabled checks pass.

Common situations: Frontend forgetting to append ?src=; copy-paste error in the URL; query string dropped by a form encoding bug; ?src= encoded in the path instead of the query.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/f1c336ebf9db8f85. Report an issue: GitHub.