{"record":{"id":"e66c3e5ef0a1fa94","repo":"mastra-ai/mastra","slug":"no-writable-mount-available-for-skill-installation","errorCode":null,"errorMessage":"No writable mount available for skill installation","messagePattern":"No writable mount available for skill installation","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"packages/server/src/server/handlers/workspace.ts","lineNumber":227,"sourceCode":"      if (!mountFs) {\n        throw new HTTPException(400, {\n          message: `Mount \"${requestedMount}\" not found. Available mounts: ${filesystem.mountPaths.join(', ')}`,\n        });\n      }\n      if (mountFs.readOnly) {\n        throw new HTTPException(403, { message: `Mount \"${requestedMount}\" is read-only` });\n      }\n      return `${stripTrailingSlash(requestedMount)}/${SKILLS_SH_DIR}/${safeSkillId}`;\n    }\n\n    // Default: use first writable mount\n    for (const [mountPath, mountFs] of filesystem.mounts) {\n      if (!mountFs.readOnly) {\n        return `${stripTrailingSlash(mountPath)}/${SKILLS_SH_DIR}/${safeSkillId}`;\n      }\n    }\n\n    throw new HTTPException(403, { message: 'No writable mount available for skill installation' });\n  }\n\n  // Non-composite: standard path\n  return `${SKILLS_SH_DIR}/${safeSkillId}`;\n}\n\n// =============================================================================\n// List All Workspaces Route\n// =============================================================================\n\nexport const LIST_WORKSPACES_ROUTE = createRoute({\n  method: 'GET',\n  path: '/workspaces',\n  responseType: 'json',\n  responseSchema: listWorkspacesResponseSchema,\n  summary: 'List all workspaces',\n  description: 'Returns all workspaces from both Mastra instance and agents',\n  tags: ['Workspace'],","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workspace.ts#L209-L245","documentation":"Thrown by buildSkillInstallPath when installing a skill without specifying a mount in a CompositeFilesystem where every registered mount is read-only. The server cannot find any mount to write into and responds with HTTP 403. It exists to fail fast instead of attempting a doomed write.","triggerScenarios":"POSTing to the skill install endpoint (installPath) with no mount parameter against a workspace whose CompositeFilesystem has all mounts configured readOnly: true, or whose only writable mount was switched to read-only after a config update.","commonSituations":"Production/staging environments locked down to read-only filesystems where skills.sh installs are still attempted; forgotten migration after mounting datasets or templates as immutable.","solutions":["Configure at least one writable mount in the workspace's CompositeFilesystem (readOnly: false) and retry.","Or enable skill installation only in environments where a writable mount exists; gate the install step by environment.","Verify with GET the workspace's filesystem/mounts that at least one mount lacks the readOnly flag before installing."],"exampleFix":"// before: all mounts read-only\nnew CompositeFilesystem({ mounts: { '/data': fs({ readOnly: true }) } })\n// after: add a writable mount for skills\nnew CompositeFilesystem({ mounts: { '/data': fs({ readOnly: true }), '/workspace': fs({ readOnly: false }) } })","handlingStrategy":"validation","validationCode":"const mountInfo = await getWorkspaceMountInfo(workspaceId);\nif (!mountInfo.some(m => !m.readOnly)) {\n  throw new Error('Workspace has no writable mount; skill installation is impossible until config changes');\n}","typeGuard":"function hasWritableMount(mounts: { readOnly: boolean }[]): boolean {\n  return mounts.some(m => !m.readOnly);\n}","tryCatchPattern":"try {\n  await installSkill({ workspaceId, skillId });\n} catch (e) {\n  if (isHttpException(e, 403) && e.message.includes('No writable mount')) {\n    logger.warn('Skipping skill install: workspace is fully read-only');\n    return { skipped: true };\n  }\n  throw e;\n}","preventionTips":["Ensure every environment where skill installs run has at least one readOnly: false mount.","Fail fast in pipeline setup by asserting a writable mount exists.","Keep install-capable environments separate from fully-immutable ones."],"tags":["workspace","filesystem","mount","read-only","skill-install"],"backgroundTag":"read-only-filesystem","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}