{"record":{"id":"1ce7dee60e9a24f0","repo":"danny-avila/LibreChat","slug":"user-id-not-found-in-blob-path","errorCode":null,"errorMessage":"User ID not found in blob path","messagePattern":"User ID not found in blob path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/server/services/Files/Azure/crud.js","lineNumber":130,"sourceCode":"    throw error;\n  }\n}\n\n/**\n * Deletes a blob from Azure Blob Storage.\n *\n * @param {Object} params\n * @param {ServerRequest} params.req - The Express request object.\n * @param {MongoFile} params.file - The file object.\n */\nasync function deleteFileFromAzure(req, file) {\n  await deleteRagFile({ userId: req.user.id, file });\n\n  try {\n    const containerClient = await getAzureContainerClient(AZURE_CONTAINER_NAME);\n    const blobPath = file.filepath.split(`${AZURE_CONTAINER_NAME}/`)[1];\n    if (!blobPath.includes(req.user.id)) {\n      throw new Error('User ID not found in blob path');\n    }\n    const blockBlobClient = containerClient.getBlockBlobClient(blobPath);\n    await blockBlobClient.delete();\n    logger.debug('[deleteFileFromAzure] Blob deleted successfully from Azure Blob Storage');\n  } catch (error) {\n    logger.error('[deleteFileFromAzure] Error deleting blob:', error);\n    if (error.statusCode === 404) {\n      return;\n    }\n    throw error;\n  }\n}\n\n/**\n * Streams a file from disk directly to Azure Blob Storage without loading\n * the entire file into memory.\n *\n * @param {Object} params","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/services/Files/Azure/crud.js#L112-L148","documentation":"Thrown by deleteFileFromAzure (Azure/crud.js) as an authorization guard: the blob path derived from file.filepath must contain req.user.id before a delete is issued. This prevents one user from deleting another user's blob by manipulating a file reference.","triggerScenarios":"file.filepath split on `${AZURE_CONTAINER_NAME}/` yields a suffix that does not include req.user.id — e.g. a cross-user file reference, a path stored without the userId segment, or a container-name mismatch.","commonSituations":"AZURE_CONTAINER_NAME env var changed after files were stored (so the split produces the wrong suffix); a file record was migrated/imported without the canonical {basePath}/{userId}/{fileName} layout; an attempt to delete a shared/system file through a user-scoped handler.","solutions":["Verify file.filepath matches the expected layout `{basePath}/{userId}/{fileName}` and that userId is present.","Confirm AZURE_CONTAINER_NAME matches the container used when the file was originally stored.","For shared/admin deletions, route through a privileged path that intentionally bypasses this ownership check.","Audit the File document in MongoDB to ensure filepath wasn't overwritten by a bad migration."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm ownership layout before delegating to deleteFileFromAzure\nconst expected = `${AZURE_CONTAINER_NAME}/${basePath}/${req.user.id}/`;\nif (!file.filepath || !file.filepath.startsWith(expected)) {\n  throw new Error('File path does not belong to this user');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await deleteFileFromAzure(req, file);\n} catch (err) {\n  if (/User ID not found in blob path/.test(err.message)) {\n    return res.status(403).json({ message: 'Not authorized to delete this file' });\n  }\n  throw err;\n}","preventionTips":["Always store Azure blobs at {basePath}/{userId}/{fileName}.","Keep AZURE_CONTAINER_NAME stable across the file's lifecycle.","Route shared/admin deletions through a privileged handler, not the user-scoped one."],"tags":["security","authorization","azure","storage","ownership"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}