{"record":{"id":"580dc1b69b31eea0","repo":"dotnet/aspnetcore","slug":"setting-nameof-notfound-and-nameof-notfoundpag","errorCode":null,"errorMessage":"Setting {nameof(NotFound)} and {nameof(NotFoundPage)} properties simultaneously is not supported. Use either {nameof(NotFound)} or {nameof(NotFoundPage)}.","messagePattern":"Setting (.+?) and (.+?) properties simultaneously is not supported\\. Use either (.+?) or (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Routing/Router.cs","lineNumber":143,"sourceCode":"        if (AppAssembly == null)\n        {\n            throw new InvalidOperationException($\"The {nameof(Router)} component requires a value for the parameter {nameof(AppAssembly)}.\");\n        }\n\n        // Found content is mandatory, because even though we could use something like <RouteView ...> as a\n        // reasonable default, if it's not declared explicitly in the template then people will have no way\n        // to discover how to customize this (e.g., to add authorization).\n        if (Found == null)\n        {\n            throw new InvalidOperationException($\"The {nameof(Router)} component requires a value for the parameter {nameof(Found)}.\");\n        }\n\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            {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/Routing/Router.cs#L125-L161","documentation":"Router exposes two ways to customize the 404 experience: the legacy NotFound render fragment and the newer NotFoundPage type (a routable component used as the 404 target). They are mutually exclusive because both would attempt to claim the not-found path; setting both at parameter-set time throws InvalidOperationException. The legacy member is decorated [Obsolete] and the warning is suppressed only around the check.","triggerScenarios":"Setting both NotFound=\"@(...)\" and NotFoundPage=\"typeof(SomeComponent)\" on the same <Router> instance. Also by setting them via SetParametersAsync in test code.","commonSituations":"Migrating from NotFound to NotFoundPage and forgetting to remove the old attribute; copy-pasting across templates that use different approaches; IDE auto-completion adding both attributes.","solutions":["Choose one mechanism: keep NotFound (render fragment) for inline markup, or NotFoundPage (a routable component) for a full-page 404 — not both.","Remove whichever attribute you are not using from the Router markup.","If migrating, delete NotFound from markup at the same commit that introduces NotFoundPage."],"exampleFix":"// before\n<Router AppAssembly=\"@typeof(Program).Assembly\"\n        NotFound=\"@NotFoundTemplate\"\n        NotFoundPage=\"@typeof(NotFoundPage)\">  <!-- both set -->\n// after — pick one\n<Router AppAssembly=\"@typeof(Program).Assembly\"\n        NotFoundPage=\"@typeof(NotFoundPage)\">","handlingStrategy":"validation","validationCode":"// Choose one not-found mechanism; this is a markup-level discipline.\n// <Router ... NotFoundPage=\"@typeof(NotFound)\">  // do NOT also set NotFound","typeGuard":"static bool IsExclusiveNotFoundSet(RenderFragment? notFound, Type? notFoundPage)\n    => !(notFound is not null && notFoundPage is not null);","tryCatchPattern":null,"preventionTips":["Decide on one 404 strategy for the project (NotFound fragment vs NotFoundPage component) and document it.","When migrating from NotFound to NotFoundPage, remove the old attribute in the same commit.","Use code review to catch accidental double-sets.","Add a startup smoke test rendering App.razor."],"tags":["blazor","routing","router","notfound","configuration","invalidoperationexception"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}