Budibase/budibase · error · HTTPError

Failed to download SharePoint file (${response.status})

Error message

Failed to download SharePoint file (${response.status})

What it means

Thrown when the Microsoft Graph download of a SharePoint file's content returns a non-ok response that is not 401/403. The failing status is logged (with driveId and itemId) before throwing an HTTPError with status 400. It distinguishes content-download failures from metadata-fetch failures.

Source

Thrown at packages/server/src/sdk/workspace/ai/knowledgeSources/sharepoint/connection.ts:899

  itemId: string,
  signal?: AbortSignal
) => {
  const response = await fetch(
    `${SHAREPOINT_API_BASE}/drives/${driveId}/items/${itemId}/content`,
    {
      signal,
      headers: {
        Authorization: bearerToken,
      },
    }
  )
  if (!response.ok) {
    console.error("Failed to download SharePoint file", {
      status: response.status,
      driveId,
      itemId,
    })
    throw new HTTPError(
      response.status === 401 || response.status === 403
        ? "Access denied by Microsoft Graph. Ensure delegated SharePoint read permissions are granted."
        : `Failed to download SharePoint file (${response.status})`,
      400
    )
  }
  return Buffer.from(await response.arrayBuffer())
}

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Check the logged status for the specific driveId/itemId; retry with backoff on 429/5xx
  2. Confirm the file still exists at the itemId (a 404 means it was deleted/moved — re-sync the drive listing)
  3. Reduce sync concurrency to avoid Graph throttling
  4. Verify download policy on the SharePoint site allows content export

Example fix

// before: immediate throw on non-ok
if (!response.ok) { throw new HTTPError(`Failed to download SharePoint file (${response.status})`, 400) }
// after: one retry on transient statuses
if (!response.ok && (response.status === 429 || response.status >= 500)) {
  response = await fetch(url, init) // retry once after delay
}
if (!response.ok) { throw new HTTPError(`Failed to download SharePoint file (${response.status})`, 400) }
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: confirm the item still exists before downloading content
const meta = await fetch(`${graphUrl}/drives/${driveId}/items/${itemId}`, { headers: { Authorization: `Bearer ${token}` } })
if (meta.status === 404) return skipFile(itemId) // deleted/moved

Try / catch

try {
  await downloadSharePointFile(conn, driveId, itemId)
} catch (e) {
  if (e instanceof HTTPError && e.message.includes("Failed to download SharePoint file")) {
    log.warn({ driveId, itemId }, "sharepoint download failed, skipping file")
    return null
  }
  throw e
}

Prevention

When it happens

Trigger: The Graph content endpoint (e.g. /drives/{driveId}/items/{itemId}/content) responds 404 (file deleted), 429 (throttled), 302-follow failures, or 5xx while downloading a file for AI knowledge ingestion. 401/403 produce the access-denied message instead.

Common situations: Large-file downloads throttled by Graph during bulk knowledge-source syncs; the file was moved/deleted between listing and download; OneDrive personal files blocked from download by policy.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/71139f65d9b81307. Report an issue: GitHub.