{"record":{"id":"ec02fdf35a935f02","repo":"danny-avila/LibreChat","slug":"storage-backend-source-does-not-support-file","errorCode":null,"errorMessage":"Storage backend \"${source}\" does not support file writes","messagePattern":"Storage backend \"(.+?)\" does not support file writes","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/server/routes/skills.js","lineNumber":150,"sourceCode":"      ? withDeploymentSkillIds(await findPubliclyAccessibleResources(params))\n      : findPubliclyAccessibleResources(params),\n  hasPublicPermission: async (params) =>\n    params.resourceType === 'skill' && params.requiredPermissions === PermissionBits.VIEW\n      ? withDeploymentSkillIds([]).some((id) => id.toString() === params.resourceId.toString()) ||\n        hasPublicPermission(params)\n      : hasPublicPermission(params),\n  grantPermission,\n  isValidObjectIdString,\n});\n\n// ---------------------------------------------------------------------------\n// File storage helper: resolve the active strategy's saveBuffer\n// ---------------------------------------------------------------------------\nfunction resolveSkillStorage(req, { isImage = false } = {}) {\n  const source = getFileStrategy(req.config, { context: FileContext.skill_file, isImage });\n  const strategy = getStrategyFunctions(source);\n  if (!strategy.saveBuffer) {\n    throw new Error(`Storage backend \"${source}\" does not support file writes`);\n  }\n  return { saveBuffer: strategy.saveBuffer, source };\n}\n\n// ---------------------------------------------------------------------------\n// Import handler (zip/md/skill → create skill + files)\n// ---------------------------------------------------------------------------\nconst importHandler = createImportHandler({\n  limits: (req) => ({\n    maxZipBytes: getSkillImportSizeLimit(req),\n  }),\n  createSkill,\n  getSkillById,\n  deleteSkill,\n  upsertSkillFile,\n  saveBuffer: (req, { userId, buffer, fileName, basePath, isImage, tenantId }) => {\n    const requestTenantId = tenantId ?? resolveRequestTenantId(req);\n    const storage = resolveSkillStorage(req, { isImage });","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/routes/skills.js#L132-L168","documentation":"Thrown by resolveSkillStorage in the skills route when the file strategy resolved for the skill_file context has no saveBuffer function. The selected storage backend (e.g. local, s3) must implement buffer writes for skill file creation/import to work; a backend that only supports reads is rejected.","triggerScenarios":"The configured FILE_STRATEGY (or the value returned by getFileStrategy for the skill_file context) points at a read-only or partially-implemented strategy whose getStrategyFunctions result lacks saveBuffer.","commonSituations":"A custom storage plugin registered without a saveBuffer implementation; deployment wired to a read-only CDN source; a deployment-mode skill file source selected where writes are not supported.","solutions":["Point the skill_file context at a strategy that implements saveBuffer (local or s3).","If using a custom strategy, implement and register a saveBuffer method on it.","Verify FILE_STRATEGY / getFileStrategy config returns the expected backend for the skill context.","Disable skill file import/upload until a writable backend is configured."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const strategy = getStrategyFunctions(source);\nif (typeof strategy.saveBuffer !== 'function') {\n  throw new Error(`Refusing skill import: backend '${source}' cannot write files`);\n}","typeGuard":"function strategyCanWrite(strategy) {\n  return strategy != null && typeof strategy.saveBuffer === 'function';\n}","tryCatchPattern":"try { await importHandler(req, res); }\ncatch (e) { if (/does not support file writes/.test(e.message)) return res.status(400).json({ error: 'Configured storage cannot receive skill files' }); throw e; }","preventionTips":["Smoke-test saveBuffer at startup for the configured skill_file strategy.","Keep a writable strategy (local/s3) for any environment that allows skill uploads.","Document which storage backends are write-capable."],"tags":["skills","storage","configuration","file-upload"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}