{"record":{"id":"009219d27f078456","repo":"dotnet/aspnetcore","slug":"the-type-notfoundpage-fullname-does-not-have-a","errorCode":null,"errorMessage":"The type {NotFoundPage.FullName} does not have a {typeof(RouteAttribute).FullName} applied to it.","messagePattern":"The type (.+?) does not have a (.+?) applied to it\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Routing/Router.cs","lineNumber":155,"sourceCode":"\n        if (NotFoundPage != null)\n        {\n#pragma warning disable CS0618 // Type or member is obsolete\n            if (NotFound != null)\n            {\n                throw new InvalidOperationException($\"Setting {nameof(NotFound)} and {nameof(NotFoundPage)} properties simultaneously is not supported. Use either {nameof(NotFound)} or {nameof(NotFoundPage)}.\");\n            }\n#pragma warning restore CS0618 // Type or member is obsolete\n            if (!typeof(IComponent).IsAssignableFrom(NotFoundPage))\n            {\n                throw new InvalidOperationException($\"The type {NotFoundPage.FullName} \" +\n                    $\"does not implement {typeof(IComponent).FullName}.\");\n            }\n\n            var routeAttributes = NotFoundPage.GetCustomAttributes(typeof(RouteAttribute), inherit: true);\n            if (routeAttributes.Length == 0)\n            {\n                throw new InvalidOperationException($\"The type {NotFoundPage.FullName} \" +\n                    $\"does not have a {typeof(RouteAttribute).FullName} applied to it.\");\n            }\n\n            var routeAttribute = (RouteAttribute)routeAttributes[0];\n            if (routeAttribute.Template != null)\n            {\n                _notFoundPageRoute = routeAttribute.Template;\n            }\n        }\n\n        if (!_onNavigateCalled)\n        {\n            _onNavigateCalled = true;\n            await RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), isNavigationIntercepted: false);\n        }\n        else\n        {\n            Refresh(isNavigationIntercepted: false);","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/Routing/Router.cs#L137-L173","documentation":"Router also requires the NotFoundPage type to carry a [Route] attribute (its route template is captured to drive the 404 navigation). The check fetches custom attributes of type RouteAttribute and throws if none are present. Without a [Route] the router cannot build a route entry for the not-found page, so the configuration is rejected at startup.","triggerScenarios":"Setting NotFoundPage to a component type that has no [Route(\"...\")] attribute on it (e.g. a layout component or a non-routed component).","commonSituations":"Reusing a layout or shared component as the 404 page; creating a NotFound component and forgetting the @page directive; refactoring a component and removing its @page thinking it is unused.","solutions":["Add @page \"/not-found\" (or equivalent [Route(\"/not-found\")]) to the top of the component referenced by NotFoundPage.","Confirm the attribute survives trimming/publishing — attributes on the type are required at runtime.","Pick a different component that already has a [Route]."],"exampleFix":"// before — NotFound.razor has no @page\n<h1>404</h1>\n// after\n@page \"/not-found\"\n<h1>404</h1>","handlingStrategy":"type-guard","validationCode":"var attrs = notFoundPage?.GetCustomAttributes(typeof(RouteAttribute), inherit: true);\nif (attrs is null || attrs.Length == 0)\n    throw new InvalidOperationException($\"{notFoundPage} needs a [Route] attribute.\");","typeGuard":"static bool HasRouteAttribute(Type? t)\n    => t?.GetCustomAttributes(typeof(RouteAttribute), inherit: true).Length > 0;","tryCatchPattern":null,"preventionTips":["Always add @page \"/not-found\" (or another route) to the component used as NotFoundPage.","Add a unit test asserting the NotFoundPage type carries a [Route].","When trimming, ensure route attributes are preserved on the not-found component."],"tags":["blazor","routing","router","notfound","route-attribute","invalidoperationexception"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}