danny-avila/LibreChat · error

Failed to fetch URL: ${response.status} ${response.statusTex

Error message

Failed to fetch URL: ${response.status} ${response.statusText}

What it means

Thrown by saveURLToFirebase (Firebase/crud.js) when the remote-file fetch returns a non-2xx status, before attempting uploadBytes to the Firebase storage ref. Identical contract to the Azure variant (error 81) — both share assertRemoteFileURL, timeout, and size caps.

Source

Thrown at api/server/services/Files/Firebase/crud.js:73

 *
 * @returns {Promise<{ bytes: number, type: string, dimensions: Record<string, number>} | null>}
 *          A promise that resolves to the file metadata if the file is successfully saved, or null if there is an error.
 */
async function saveURLToFirebase({ userId, URL, fileName, basePath = 'images' }) {
  const storage = getFirebaseStorage();
  if (!storage) {
    logger.error('Firebase is not initialized. Cannot save file to Firebase Storage.');
    return null;
  }

  const storageRef = ref(storage, `${basePath}/${userId.toString()}/${fileName}`);
  const maxBytes = getRemoteFileFetchMaxBytes();
  const response = await fetch(assertRemoteFileURL(URL), {
    timeout: getRemoteFileFetchTimeoutMs(),
    size: maxBytes,
  });
  if (!response.ok) {
    throw new Error(`Failed to fetch URL: ${response.status} ${response.statusText}`);
  }
  assertRemoteFileContentLength(response.headers, maxBytes);
  const buffer = await response.buffer();
  if (buffer.length > maxBytes) {
    throw new Error(`Remote file response too large: ${buffer.length} bytes`);
  }

  try {
    await uploadBytes(storageRef, buffer);
    return await getBufferMetadata(buffer);
  } catch (error) {
    logger.error('Error uploading file to Firebase Storage:', error.message);
    return null;
  }
}

/**
 * Retrieves the download URL for a specified file from Firebase Storage. This function initializes the

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Verify the URL is publicly reachable (curl -I returns 2xx).
  2. If the origin needs auth, fetch via a proxy that injects headers.
  3. Distinguish 403/404 in the caller to give the user an accurate message.
  4. Confirm the URL scheme is http/https (assertRemoteFileURL enforces this).
Defensive patterns

Strategy: validation

Validate before calling

// HEAD-check the URL before downloading
const head = await fetch(assertRemoteFileURL(URL), { method: 'HEAD', timeout: getRemoteFileFetchTimeoutMs() });
if (!head.ok) {
  throw new Error(`Preflight failed: ${head.status} ${head.statusText}`);
}

Try / catch

try {
  await saveURLToFirebase({ userId, URL, fileName, basePath });
} catch (err) {
  const m = /^Failed to fetch URL: (\d{3})/.exec(err.message);
  if (m) {
    const status = Number(m[1]);
    return res.status(status === 404 || status === 403 ? status : 502)
      .json({ message: `Remote URL returned ${status}` });
  }
  throw err;
}

Prevention

When it happens

Trigger: A remote URL passed to the Firebase save path returns non-2xx (404/403/500) from the origin, or the origin redirects into an error.

Common situations: Expired signed URL; origin requires auth; URL typo or dead link; geo-blocked origin; origin server down.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/748ebe1432c82b93. Report an issue: GitHub.