{"record":{"id":"2259e206b02a8498","repo":"dotnet/aspnetcore","slug":"valueless-attributes-may-only-be-added-immediately","errorCode":null,"errorMessage":"Valueless attributes may only be added immediately after frames of type {RenderTreeFrameType.Element}","messagePattern":"Valueless attributes may only be added immediately after frames of type (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Rendering/RenderTreeBuilder.cs","lineNumber":174,"sourceCode":"    /// <param name=\"textContent\">Content for the new text frame.</param>\n    public void AddContent(int sequence, object? textContent)\n        => AddContent(sequence, textContent?.ToString());\n\n    /// <summary>\n    /// <para>\n    /// Appends a frame representing a bool-valued attribute with value 'true'.\n    /// </para>\n    /// <para>\n    /// The attribute is associated with the most recently added element.\n    /// </para>\n    /// </summary>\n    /// <param name=\"sequence\">An integer that represents the position of the instruction in the source code.</param>\n    /// <param name=\"name\">The name of the attribute.</param>\n    public void AddAttribute(int sequence, string name)\n    {\n        if (_lastNonAttributeFrameType != RenderTreeFrameType.Element)\n        {\n            throw new InvalidOperationException($\"Valueless attributes may only be added immediately after frames of type {RenderTreeFrameType.Element}\");\n        }\n\n        _entries.AppendAttribute(sequence, name, ElementBoolTrueValue);\n    }\n\n    /// <summary>\n    /// <para>\n    /// Appends a frame representing a bool-valued attribute.\n    /// </para>\n    /// <para>\n    /// The attribute is associated with the most recently added element. If the value is <c>false</c> and the\n    /// current element is not a component, the frame will be omitted.\n    /// </para>\n    /// </summary>\n    /// <param name=\"sequence\">An integer that represents the position of the instruction in the source code.</param>\n    /// <param name=\"name\">The name of the attribute.</param>\n    /// <param name=\"value\">The value of the attribute.</param>\n    public void AddAttribute(int sequence, string name, bool value)","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/Components/src/Rendering/RenderTreeBuilder.cs#L156-L192","documentation":"AddAttribute(int, string) (the valueless/bool-true overload) was called when the last non-attribute frame on the builder was not an Element. Valueless attributes like `@bind`-less boolean HTML attributes are only meaningful on elements, so the builder rejects attaching one to a component or at the root.","triggerScenarios":"Calling builder.AddAttribute(seq, \"disabled\") before any OpenElement, or right after OpenComponent. Razor compiling an attribute on a component using a valueless Razor directive attribute syntax.","commonSituations":"Authoring custom component bases / manual RenderTreeBuilder code. Razor syntax that emits a valueless attribute against a component tag. Misordering builder calls.","solutions":["Ensure OpenElement(...) was the most recent non-attribute frame before calling AddAttribute(seq, name).","If the attribute is for a component parameter, use AddComponentParameter or the typed AddAttribute overloads instead.","Reorder builder calls so the valueless attribute follows the element opening."],"exampleFix":"// before\nbuilder.AddAttribute(0, \"readonly\"); // no element open\nbuilder.OpenElement(1, \"input\");\n\n// after\nbuilder.OpenElement(0, \"input\");\nbuilder.AddAttribute(1, \"readonly\");","handlingStrategy":"validation","validationCode":"// In custom builders, guard before valueless attribute\nif (lastNonAttributeFrameType != RenderTreeFrameType.Element)\n    throw new InvalidOperationException(\"Open an element first.\");\nbuilder.AddAttribute(seq, name);","typeGuard":"static bool CanAddValuelessAttribute(RenderTreeFrameType last) => last == RenderTreeFrameType.Element;","tryCatchPattern":null,"preventionTips":["Call OpenElement before any valueless AddAttribute(seq, name).","Prefer authoring via Razor, which emits the correct order automatically."],"tags":["blazor","render-tree-builder","attribute","api-misuse"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}