{"record":{"id":"8973e3bcd4c69a33","repo":"AlistGo/alist","slug":"authentication-required","errorCode":null,"errorMessage":"authentication required","messagePattern":"authentication required","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"server/mcp/auth.go","lineNumber":106,"sourceCode":"\treturn user, nil\n}\n\nfunc loadRoles(user *model.User) error {\n\tif len(user.Role) > 0 {\n\t\troles, err := op.GetRolesByUserID(user.ID)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load roles: %w\", err)\n\t\t}\n\t\tuser.RolesDetail = roles\n\t}\n\treturn nil\n}\n\n// resolveUser extracts the authenticated user from context.\nfunc resolveUser(ctx context.Context) (*model.User, error) {\n\tuser, ok := ctx.Value(userKey).(*model.User)\n\tif !ok || user == nil {\n\t\treturn nil, fmt.Errorf(\"authentication required\")\n\t}\n\treturn user, nil\n}\n\n// buildFsContext resolves path and sets meta in context for fs operations.\nfunc buildFsContext(ctx context.Context, user *model.User, path string) (context.Context, string, error) {\n\treqPath, err := user.JoinPath(path)\n\tif err != nil {\n\t\treturn ctx, \"\", err\n\t}\n\tmeta, _ := op.GetNearestMeta(reqPath)\n\tctx = context.WithValue(ctx, \"meta\", meta)\n\tctx = context.WithValue(ctx, \"user\", user)\n\treturn ctx, reqPath, nil\n}\n\n// checkAccess checks if user can access the path (read).\nfunc checkAccess(user *model.User, reqPath string) error {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/mcp/auth.go#L88-L124","documentation":"Returned by resolveUser (server/mcp/auth.go:106) when an MCP tool handler finds no *model.User under the context userKey. The auth middleware logs 'MCP auth failed' and passes the request through with no user, so this fires for requests whose token failed authentication (or was never sent) and later reached a tool requiring a user.","triggerScenarios":"MCP tool call with a missing or blank Authorization header; a token that failed one of the authenticateToken checks (invalid, disabled user, etc.) while the connection itself was still accepted.","commonSituations":"MCP clients configured without auth; tokens silently expired mid-session; middleware ordering changes letting unauthenticated contexts reach tools.","solutions":["Send a valid Authorization header/token with every MCP request","If a token was working, find the earlier 'MCP auth failed' log line naming the real reason","Make tool calls fail fast on missing auth instead of continuing the session"],"exampleFix":"// before\nclient.connect({ url: \"http://host/mcp\" })\n// after\nclient.connect({ url: \"http://host/mcp\", headers: { Authorization: \"Bearer <token>\" } })","handlingStrategy":"validation","validationCode":"if cfg.Token == \"\" { return fmt.Errorf(\"MCP token not configured — request will fail with authentication required\") }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"authentication required\") { checkToken(); sendFreshToken(); retryOnce() }","preventionTips":["Always configure auth in MCP clients","Fail fast client-side on missing credentials","Correlate with server 'MCP auth failed' logs to find the root cause"],"tags":["mcp","auth","middleware"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}