transloadit/uppy · error · Error

URL server responded with status: ${urlMeta.statusCode}

Error message

URL server responded with status: ${urlMeta.statusCode}

What it means

Companion's getURLMeta fetches metadata (name, size, type) for a remote URL via a HEAD request (falling back to GET when the HEAD response is >=400 or has no size). If the final response status code is 300 or above, the remote server is considered to have failed and this error is thrown, embedding the status code in the message. It surfaces through Companion's /url/meta endpoint when a user adds a file by URL.

Source

Thrown at packages/@uppy/companion/src/server/helpers/request.ts:253

    )
  }

  // We prefer to use a HEAD request, as it doesn't download the content. If the URL doesn't
  // support HEAD, or doesn't follow the spec and provide the correct Content-Length, we
  // fallback to GET.
  let urlMeta = await requestWithMethod('HEAD')

  // If HTTP error response, we retry with GET, which may work on non-compliant servers
  // (e.g. HEAD doesn't work on signed S3 URLs)
  // We look for status codes in the 400 and 500 ranges here, as 3xx errors are
  // unlikely to have to do with our choice of method
  // todo add unit test for this
  if (urlMeta.statusCode >= 400 || urlMeta.size === 0 || urlMeta.size == null) {
    urlMeta = await requestWithMethod('GET')
  }

  if (urlMeta.statusCode >= 300) {
    throw new Error(`URL server responded with status: ${urlMeta.statusCode}`)
  }

  const { name, size, type } = urlMeta
  return { name, size, type }
}

View on GitHub (pinned to 5d4dedd02a)

Solutions

  1. Verify the URL responds with 2xx from a server context (curl -I <url>) — if not, the URL itself is the problem (expired/typo/auth-required)
  2. If the server rejects HEAD with 4xx/5xx, ensure it serves valid Content-Length and Content-Type on GET so the fallback succeeds
  3. If the host blocks Companion's requests (firewall/UA filtering), allowlist Companion's IP or user-agent, or proxy the download through an endpoint that responds correctly
  4. Catch this error in the client and surface a user-facing message telling them the link is unreachable

Example fix

// before
const meta = await companionClient.urlMeta('https://cdn.example.com/file.pdf')

// after
try {
  const meta = await companionClient.urlMeta('https://cdn.example.com/file.pdf')
} catch (err) {
  if (/URL server responded with status/.test(err.message)) {
    throw new Error('This link could not be reached. It may be expired or require login.')
  }
  throw err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check reachability before handing the URL to Companion
async function urlIsReachable(url) {
  const res = await fetch(url, { method: 'HEAD' }).catch(() => null)
  if (!res || res.status >= 300) return false
  const len = Number(res.headers.get('content-length'))
  return Number.isFinite(len) && len > 0
}

Type guard

function isUrlMetaError(err: unknown): boolean {
  return err instanceof Error && /^URL server responded with status: \d+$/.test(err.message)
}

Try / catch

try {
  const { name, size, type } = await uppy.getPlugin('Url').getUrlMeta(url)
} catch (err) {
  if (isUrlMetaError(err)) return notifyUser('This link is unreachable or expired.')
  throw err
}

Prevention

When it happens

Trigger: Calling POST /url/meta (or the uppy.addUrl / addFiles with remote URL flow) where the target server responds with a redirect that isn't followed, a 4xx/5xx to both HEAD and GET, or the URL points to a page that doesn't serve the file directly (e.g. an expired signed link, a login page returning 403, or an HTML error page).

Common situations: Expired pre-signed S3/Azure URLs, links behind authentication that return 401/403, servers that reject HEAD requests with 405 and also fail GET, or copy-pasted URLs with typos producing 404. Also occurs when the remote host blocks Companion's user agent or IP.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of transloadit/uppy@5d4dedd02a (2026-08-28). Data as JSON: /api/errors/afb4fc685c657285. Report an issue: GitHub.