AlistGo/alist · error
permission denied
Error message
permission denied
What it means
Returned by checkAccess (server/mcp/auth.go:127) when common.CanAccessWithRoles rejects the user for reqPath based on the nearest meta's access rules. This is the read-level path gate evaluated before any MCP permission bit: the user's roles must satisfy the meta visibility and role restrictions attached to the path or a parent directory.
Source
Thrown at server/mcp/auth.go:127
}
// buildFsContext resolves path and sets meta in context for fs operations.
func buildFsContext(ctx context.Context, user *model.User, path string) (context.Context, string, error) {
reqPath, err := user.JoinPath(path)
if err != nil {
return ctx, "", err
}
meta, _ := op.GetNearestMeta(reqPath)
ctx = context.WithValue(ctx, "meta", meta)
ctx = context.WithValue(ctx, "user", user)
return ctx, reqPath, nil
}
// checkAccess checks if user can access the path (read).
func checkAccess(user *model.User, reqPath string) error {
meta, _ := op.GetNearestMeta(reqPath)
if !common.CanAccessWithRoles(user, meta, reqPath, "") {
return fmt.Errorf("permission denied")
}
perm := common.MergeRolePermissions(user, reqPath)
if !user.IsAdmin() && !common.HasPermission(perm, common.PermMCPAccess) {
return fmt.Errorf("MCP access not permitted")
}
return nil
}
// checkManage checks if user can perform write operations via MCP.
func checkManage(user *model.User, reqPath string, permBit uint) error {
if err := checkAccess(user, reqPath); err != nil {
return err
}
perm := common.MergeRolePermissions(user, reqPath)
if !user.IsAdmin() && !common.HasPermission(perm, common.PermMCPManage) {
return fmt.Errorf("MCP manage not permitted")
}
if !user.IsAdmin() && !common.HasPermission(perm, permBit) {View on GitHub (pinned to 843d9dc814)
Solutions
- Check that the user's role base path covers the requested path
- Inspect the nearest meta on the path and relax its visibility or role list if appropriate
- Switch to an account whose roles cover the path
- Remember the check walks up: a meta on any ancestor applies
Defensive patterns
Strategy: validation
Validate before calling
// before the call, confirm the path is inside one of the user's role base paths
func covered(userRoles []Role, p string) bool {
for _, r := range userRoles { if isSub(r.BasePath, p) { return true } }
return false
} Prevention
- Keep role base paths aligned with the directories tools touch
- Remember metas on ancestor directories apply to descendants
- After adding restrictive metas, re-test MCP paths
When it happens
Trigger: A non-admin user whose role scope (base path) does not cover reqPath; a directory meta marked hidden or restricted to other roles; the guest account hitting a path with a restrictive meta.
Common situations: Roles scoped to /data/team-a while the tool requests /data/team-b; metas set to private on upload roots; newly added meta restrictions breaking previously working MCP flows.
Related errors
- MCP access not permitted
- MCP manage not permitted
- permission denied for this operation
- failed to get download link
- user is not allowed to access via FTP
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/a226a24f211a36ba.
Report an issue: GitHub.