{"record":{"id":"1509df953e1d6d7a","repo":"Budibase/budibase","slug":"sharepoint-drive-does-not-belong-to-this-site","errorCode":null,"errorMessage":"SharePoint drive does not belong to this site","messagePattern":"SharePoint drive does not belong to this site","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/rag/sources/sharepoint/sharepoint.ts","lineNumber":452,"sourceCode":"          })\n        ),\n        ...lists.map(\n          (list): KnowledgeSourceEntry => ({\n            id: `list:${list.id}`,\n            name: list.name,\n            path: list.name,\n            type: \"list\",\n            listId: list.id,\n            webUrl: list.webUrl,\n          })\n        ),\n      ].sort((a, b) => a.name.localeCompare(b.name)),\n    }\n  }\n\n  const drive = drives.find(candidate => candidate.id === driveId)\n  if (!drive) {\n    throw new HTTPError(\"SharePoint drive does not belong to this site\", 400)\n  }\n\n  const resolvedParentPath = parentPath.trim() || drive.name\n  const items = await listSharePointDriveItems(\n    bearerToken,\n    driveId,\n    parentItemId\n  )\n  return {\n    entries: items\n      .filter(\n        (item): item is SharePointDriveItem & { id: string; name: string } =>\n          !!item.id && !!item.name && !!(item.folder || item.file)\n      )\n      .map(\n        (item): KnowledgeSourceEntry => ({\n          id: `${driveId}:${item.id}`,\n          name: item.name,","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/rag/sources/sharepoint/sharepoint.ts#L434-L470","documentation":"fetchSharePointEntriesForOperation resolves a site's drives via listSharePointDrives and then, when a driveId is supplied, verifies that the requested drive actually exists among that site's drives. If no drive in the site's drive list matches the given driveId, it throws this 400 HTTPError. It is a guard against browsing/syncing a drive that belongs to a different (or deleted) site.","triggerScenarios":"Calling the knowledge-source entries browsing flow with a driveId that is not in the drive list returned by the Graph API for the connected site's siteId — e.g. a driveId copied from another site, a stale/renamed drive, or a mismatched siteId+driveId pair.","commonSituations":"Reusing cached browse results after the source's site was changed; UI sending a driveId from a previously selected site; SharePoint drive deleted or recreated (new drive id); client bug pairing the wrong siteId with a driveId.","solutions":["Verify the driveId belongs to the same site as source.config.site.id (list the site's drives via the Graph API and match on id)","Re-fetch the drive list for the current site and pick the drive fresh instead of using a cached driveId","If the site was changed on the source, reconnect/re-save the knowledge source so siteId and driveId are consistent","Check the drive still exists in SharePoint (it may have been deleted or recreated with a new id)"],"exampleFix":"// before\nawait fetchSharePointEntriesForOperation({ agentId, operationId, siteId: siteA, driveId: driveFromSiteB })\n// after\nconst drives = await listSharePointDrives(token, siteA)\nconst drive = drives.find(d => d.name === \"Documents\")\nawait fetchSharePointEntriesForOperation({ agentId, operationId, siteId: siteA, driveId: drive.id })","handlingStrategy":"validation","validationCode":"const drives = await listSharePointDrives(bearerToken, siteId)\nif (!drives.some(d => d.id === driveId)) {\n  throw new Error(`Drive ${driveId} does not belong to site ${siteId}`)\n}","typeGuard":"const isValidDrive = (driveId: string, drives: { id: string }[]): boolean =>\n  drives.some(d => d.id === driveId)","tryCatchPattern":"try {\n  await fetchSharePointEntriesForOperation({ agentId, operationId, siteId, driveId })\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 400 && err.message.includes(\"does not belong to this site\")) {\n    // refresh drive list and re-pick the drive\n  } else { throw err }\n}","preventionTips":["Always resolve driveIds from the live drive list of the same siteId","Never cache driveIds across site changes","Refresh browse state when the source's site config changes","Handle drive recreation in SharePoint (ids change)"],"tags":["sharepoint","graph-api","validation"],"backgroundTag":"resource-not-found-in-parent","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}