Skip to content

[10.0.300] RZ1021 falsely raised for HTML tags inside @if blocks #13184

Description

@Ghostbird

Sorry, this should have been filed at dotnet/roslyn

Summary

After upgrading from .NET SDK 10.0.203 → 10.0.300, the Razor source generator falsely reports RZ1021: Markup in a code block must start with a tag and all start tags must be matched with end tags for perfectly valid markup. The generated .g.cs is corrupted: the parser eats the leading <tagname and emits everything after as raw C#, which then triggers cascading CS0102/CS9348/CS0101 errors across the whole assembly.

The trigger is surprisingly narrow:

  • The element must be inside a Razor code block (@if {}, @foreach {}, …).
  • The enclosing block must be inside outer markup (e.g. a <div>).
  • The tag name must be 4 or more characters (3-char names like <br>, <img>, <hr>, <col>, <wbr> work fine).
  • The element's line must be tab-indented or have no indentation. Space indentation works.

Minimal repro

Views/Home/Repro.cshtml:

<div>
	@if (true)
	{
		<input />
	}
</div>

(All indentation is tabs.) Build with dotnet build:

Views/Home/Repro.cshtml(4,5): error RZ1021: Markup in a code block must start with a tag and all start tags must be matched with end tags.  Do not use unclosed tags like "<br>".  Instead use self-closing tags like "<br/>".

Followed by ~10 cascading CS errors in the generated _Repro_cshtml.g.cs.

What makes it succeed

UPDATE: Spoilered, because @Magehernan encountered this in a scenario that did not match my findings.
  • It occurred for simple <div> tags, no need for 4+ characters
  • It occurred without an outer <div> tag.

Any one of the following changes makes the build succeed:

  1. Replace tab indentation with spaces.
  2. Use a tag name with ≤ 3 characters (<br />, <img />, <hr />, <col />, <wbr />).
  3. Remove the outer <div> wrapper.
  4. Disable the source generator: <UseRazorSourceGenerator>false</UseRazorSourceGenerator>.

Tag name length matrix (with tab indent, inside <div> + @if)

Tag Result
<a />, <ab />, <abc /> OK
<abcd />, <abcde /> RZ1021
<br />, <img />, <hr />, <col />, <wbr /> OK
<input />, <meta />, <link />, <area />, <base />, <embed />, <source />, <track /> RZ1021
Tag with hyphen (<aaa-bbb-ccc />) OK

So this is not about void elements specifically (otherwise <br> and <input> would behave the same); the discriminator looks like raw tag-name length combined with leading whitespace classification.

Inspecting the generated file

With EmitCompilerGeneratedFiles=true, the generated _Repro_cshtml.g.cs shows the parser bailed early — it emits <input as the start of a markup element, then puts the rest of the line and following lines as raw C# code inside a method body, producing a stream of <invalid-global-code> types that conflict with every other Razor file in the assembly. Because the cascading CS errors land in AspNetCoreGeneratedDocument, a single bad .cshtml makes every other view in the project fail to compile (CS0101, CS0102 for ModelExpressionProvider/Url/Component/Json/Html).

Environment

  • SDK: .NET SDK 10.0.300 (commit caa81fa497)
  • OS: Debian 13 (Linux x64)
  • Previously working: 10.0.203
  • Affected project: Microsoft.NET.Sdk.Web, <TargetFramework>net10.0</TargetFramework>
  • Reproduces in both Debug and Release configurations.
  • Reproduces without any tag helper imports (removing @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers does not fix it).

Impact

This silently broke a real production project after a system-wide SDK update. The error message (Do not use unclosed tags like "<br>") is actively misleading because the actual markup is well-formed self-closed <input />, and <br> itself is one of the tags that does not trigger it. A single offending file cascades into 100+ CS errors across the project, making it hard to identify the root cause without inspecting the generated source.

Workaround

<PropertyGroup>
  <UseRazorSourceGenerator>false</UseRazorSourceGenerator>
</PropertyGroup>

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions