{"record":{"id":"5cb452dd21eb15bd","repo":"dotnet/aspnetcore","slug":"sectionoutlet-requires-a-non-null-value-either-for","errorCode":null,"errorMessage":"SectionOutlet requires a non-null value either for 'SectionName' or 'SectionId'.","messagePattern":"SectionOutlet requires a non-null value either for 'SectionName' or 'SectionId'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Sections/SectionOutlet.cs","lineNumber":62,"sourceCode":"        parameters.SetParameterProperties(this);\n\n        object? identifier;\n\n        if (SectionName is not null && SectionId is not null)\n        {\n            throw new InvalidOperationException($\"{nameof(SectionOutlet)} requires that '{nameof(SectionName)}' and '{nameof(SectionId)}' cannot both have non-null values.\");\n        }\n        else if (SectionName is not null)\n        {\n            identifier = SectionName;\n        }\n        else if (SectionId is not null)\n        {\n            identifier = SectionId;\n        }\n        else\n        {\n            throw new InvalidOperationException($\"{nameof(SectionOutlet)} requires a non-null value either for '{nameof(SectionName)}' or '{nameof(SectionId)}'.\");\n        }\n\n        if (!object.Equals(identifier, _subscribedIdentifier))\n        {\n            if (_subscribedIdentifier is not null)\n            {\n                _registry.Unsubscribe(_subscribedIdentifier);\n            }\n\n            _registry.Subscribe(identifier, this);\n            _subscribedIdentifier = identifier;\n        }\n\n        RenderContent();\n\n        return Task.CompletedTask;\n    }\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/Sections/SectionOutlet.cs#L44-L80","documentation":"SectionOutlet requires a target identifier to subscribe to the registry; with neither SectionName nor SectionId the Subscribe call cannot proceed and SetParametersAsync throws InvalidOperationException. An outlet with no subscription is meaningless, so this is a hard precondition rather than a soft default.","triggerScenarios":"Declaring a bare <SectionOutlet /> or binding both identifier parameters to nullable expressions that resolve to null. Hit on every SetParametersAsync where both are null.","commonSituations":"Forgot the identifier; conditional binding evaluates to null on first render; refactored markup and dropped the attribute; built the outlet via RenderTreeBuilder without supplying either parameter.","solutions":["Add SectionName=\"name\" or SectionId=\"@nonNullObject\" to every SectionOutlet.","If the identifier is dynamic, gate the outlet behind @if (identifier != null) so it never renders identifierless.","When constructing via RenderTreeBuilder, always AddAttribute for exactly one identifier before CloseComponent."],"exampleFix":"// before\n<SectionOutlet />\n\n// after\n<SectionOutlet SectionName=\"header\" />\n// or\n@code { internal static readonly object HeaderId = new(); }\n<SectionOutlet SectionId=\"@SectionIds.HeaderId\" />","handlingStrategy":"validation","validationCode":"@if (!string.IsNullOrEmpty(sectionName) || sectionId is not null)\n{\n    <SectionOutlet SectionName=\"@sectionName\" SectionId=\"@sectionId\" />\n}","typeGuard":"static bool HasSectionIdentifier(string? name, object? id) =>\n    !string.IsNullOrEmpty(name) || id is not null;","tryCatchPattern":null,"preventionTips":["Always supply exactly one identifier to SectionOutlet.","Gate data-driven outlets behind @if (id is not null).","When building via RenderTreeBuilder, always AddAttribute one identifier."],"tags":["blazor","sections","sectionoutlet","parameters","invalidoperationexception"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}