Skip to content

Razor file formatting throws "ran out of lines" exception #11970

@vsfeedback

Description

@vsfeedback

This issue has been moved from a ticket on Developer Community.


[severity:It's more difficult to complete my work]
Having a .razor file with the below contents and then try to format it with ctrl-k,d


@inject IJSRuntime JSRuntime

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        @if (!IconMenuActive)
        {
            <a class="navbar-brand" href="">Blazor Server</a>
        }
        else
        {
            <a class="navbar-brand bi bi-window-fullscreen" />
        }
        <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>
        </button>
    </div>
</div>

<div class="@NavMenuCssClass">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="bi bi-house" aria-hidden="true"></span>
                @if (!IconMenuActive)
                {
                    <span><label>Home</label></span>
                }
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="bi bi-plus-circle" aria-hidden="true"></span>
                @if (!IconMenuActive)
                {
                    <span><label>Counter</label></span>
                }
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="weather">
                <span class="bi bi-brightness-high" aria-hidden="true"></span>
                @if (!IconMenuActive)
                {
                    <span><label>Fetch data</label></span>
                }
            </NavLink>
        </div>
        <div class="nav-item px-3" @onclick='@(() => ToggleSubMenu("subMenu1"))'>
            <NavLink class="nav-link flex-container" Match="NavLinkMatch.All">
                <span class="bi bi-folder" aria-hidden="true" title="subMenu"></span>
                @if (!IconMenuActive)
                {
                    <span><label>Sub Menu 1</label></span>
                    <span class="oi chevron-icon @(IsSubMenuOpen("subMenu1") ? "bi bi-arrow-up-short" : "bi bi-arrow-down-short")" aria-hidden="true"></span>
                }
            </NavLink>
            <div class="sub-menu" style="display: @(IsSubMenuOpen("subMenu1") ? "block" : "none")">
                <NavLink class="nav-link" href="subitem1">
                    <span class="bi bi-arrow-right-circle" aria-hidden="true" title="Sub Item 1"></span>
                    @if (!IconMenuActive)
                    {
                        <span><label>Sub Menu 1 Item 1</label></span>
                    }
                </NavLink>
                <NavLink class="nav-link" href="subitem2">
                    <span class="bi bi-arrow-right-circle" aria-hidden="true" title="Sub Item 2"></span>
                    @if (!IconMenuActive)
                    {
                        <span><label>Sub Menu 1 Item 2</label></span>
                    }
                </NavLink>
            </div>
        </div>
        <div class="nav-item px-3" @onclick='@(() => ToggleSubMenu("subMenu2"))'>
            <NavLink class="nav-link flex-container" Match="NavLinkMatch.All">
                <span class="bi bi-folder" aria-hidden="true" title="subMenu"></span>
                @if (!IconMenuActive)
                {
                    <span><label>Sub Menu 2</label></span>
                    <span class="oi chevron-icon @(IsSubMenuOpen("subMenu2") ? "bi bi-arrow-up-short" : "bi bi-arrow-down-short")" aria-hidden="true"></span>
                }
            </NavLink>
            <div class="sub-menu" style="display: @(IsSubMenuOpen("subMenu2") ? "block" : "none")">
                <NavLink class="nav-link" href="subitem1">
                    <span class="bi bi-arrow-right-circle" aria-hidden="true" title="Sub Item 1"></span>
                    @if (!IconMenuActive)
                    {
                        <span><label>Sub Menu 2 Item 1</label></span>
                    }
                </NavLink>
                <NavLink class="nav-link" href="subitem2">
                    <span class="bi bi-arrow-right-circle" aria-hidden="true" title="Sub Item 2"></span>
                    @if (!IconMenuActive)
                    {
                        <span><label>Sub Menu 2 Item 2</label></span>
                    }
                </NavLink>
            </div>
        </div>
    </nav>
</div>

<div class="bottom-row">
    <div class="icon-menu-arrow">
        @if (!IconMenuActive)
        {
            <span class="bi bi-arrow-bar-left" style="color: white;" @onclick="ToggleIconMenu"></span>
        }
        else
        {
            <span class="bi bi-arrow-bar-right" style="color: white;" @onclick="ToggleIconMenu"></span>
        }
    </div>
</div>

@code
{
    [Parameter]
    public EventCallback<bool> ShowIconMenu { get; set; }

    private bool IconMenuActive { get; set; } = false;
    private bool collapseNavMenu = true;
    private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
    private Dictionary<string, bool> subMenuStates = new Dictionary<string, bool>();

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync("setResizeCallback", DotNetObjectReference.Create(this));
        }
    }

    [JSInvokable]
    public async Task OnResize(bool isBelowThreshold)
    {
        if (isBelowThreshold && IconMenuActive)
        {
            collapseNavMenu = true;
            await ToggleIconMenu();

            await ShowIconMenu.InvokeAsync(IconMenuActive);

            await InvokeAsync(StateHasChanged);
        }
    }

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }

    private async Task ToggleIconMenu()
    {
        IconMenuActive = !IconMenuActive;

        await ShowIconMenu.InvokeAsync(IconMenuActive);
    }

    private void ToggleSubMenu(string subMenuKey)
    {
        if (subMenuStates.ContainsKey(subMenuKey) && subMenuStates[subMenuKey])
        {
            subMenuStates[subMenuKey] = false;
        }
        else
        {
            foreach (var key in subMenuStates.Keys.ToList())
            {
                subMenuStates[key] = false;
            }

            if (subMenuStates.ContainsKey(subMenuKey))
            {
                subMenuStates[subMenuKey] = !subMenuStates[subMenuKey];
            }
            else
            {
                subMenuStates[subMenuKey] = true;
            }
        }
    }

    private bool IsSubMenuOpen(string subMenuKey)
    {
        return subMenuStates.ContainsKey(subMenuKey) && subMenuStates[subMenuKey];
    }
}

throws exception

>[LSP][Formatting.New.CSharpFormattingPass] [08:28:17.0437785] Ran out of lines while trying to process formatted changes. Abandoning further formatting to not corrupt the source file, please report this issue.
>[CLaSP] [08:28:17.0584179] [null]: System.ArgumentException: The changes must not overlap. Parameter name: changes at Microsoft.CodeAnalysis.Text.SourceText.WithChanges(IEnumerable1 changes) at Microsoft.CodeAnalysis.Text.ChangedText.WithChanges(IEnumerable1 changes) at Microsoft.CodeAnalysis.Razor.Formatting.New.CSharpFormattingPass.<ExecuteAsync>d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.CodeAnalysis.Razor.Formatting.RazorFormattingService.<GetDocumentFormattingChangesAsync>d__11.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Razor.LanguageServer.Formatting.DocumentFormattingEndpoint.<HandleRequestAsync>d__8.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CommonLanguageServerProtocol.Framework.QueueItem1.&lt;StartRequestAsync&gt;d__172.MoveNext()

What might also be relevant is that I have, both in C# and Razor settings, turned on the "opening brace stays on the method/class line" setting.


Original Comments

Rami Jarakivi on 18/06/2025, 06:05 PM:

Just noticed that a much simpler razor file like this

@code
{
private bool IconMenuActive { get; set; } = false;

protected void ToggleIconMenu(bool iconMenuActive)
{
IconMenuActive = iconMenuActive;
}
}

produces a very similar, but not quite the same exception, but it could be related

[LSP][Formatting.New.CSharpFormattingPass] [11:04:45.6217604] Ran out of formatted lines while trying to process formatted changes after 7 lines. Abandoning further formatting to not corrupt the source file, please report this issue.
[CLaSP] [11:04:45.6217604] [null]: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: lineNumber at Microsoft.CodeAnalysis.Text.CompositeText.CompositeTextLineInfo.get_Item(Int32 lineNumber) at Microsoft.CodeAnalysis.Razor.Formatting.New.CSharpFormattingPass.<ExecuteAsync>d__4.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.CodeAnalysis.Razor.Formatting.RazorFormattingService.<GetDocumentFormattingChangesAsync>d__11.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Razor.LanguageServer.Formatting.DocumentFormattingEndpoint.<HandleRequestAsync>d__8.MoveNext() — End of stack trace from previous location where exception was thrown — at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.CommonLanguageServerProtocol.Framework.QueueItem1.<StartRequestAsync>d__172.MoveNext()

Feedback Bot on 18/06/2025, 06:08 PM:

We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.

David Wengier [MSFT] on 20/06/2025, 10:14 AM:

Thanks for the report! Based on our previous discussion in the last bug, this will almost certainly be due to a specific C# formatting option you have set. Last time it was K&R style braces, this time, who knows! Would it be possible for you to send through screenshots of your C# formatting options? Or attach a .editorconfig file if thats what you’re using to specify these options.

In mean time I’ll try to run through a few combinations and see if anything shakes out.

Finally, along with the previous bug fix, we also added an opt-out for you to switch to the old formatting engine which should unblock you until we can get an update out. You’ll find it in Tools -> Options -> Preview Features, or just search for “Razor” and it should come up.

Rami Jarakivi on 23/06/2025, 01:33 PM:

Can confirm that switching the Preview feature off does format the above examples for me. I have also attached my .editorconfig file.

Editorconfig.zip

Curiously just noticed that if I help it a little and place the brace on the same line in the “@code {” line, it works with the new formatting engine. So something about that code and it’s brace being on the next line seems to be breaking things.

David Wengier [MSFT] on 23/06/2025, 08:27 AM:

Interestingly, I’ve found one bug that I would imagine you’re hitting, which is where classes are configured for K&R, and you have the open brace for the code block on its own line, like in your example. The odd thing is I’m getting a different error message to you. Will fix either way. Also wondering if the open brace for the code block should simply follow the C# formatting rules that are applied to classes, rather than having our own “Code block brace on next line” setting.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions