dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.37k stars 9.99k forks source link

Unpredictable No element is currently associated with component {ComponentId} #5592

Closed vertonghenb closed 5 years ago

vertonghenb commented 6 years ago

Edited to remove the false-positives

Reproducable : https://github.com/aspnet/Blazor/issues/1412#issuecomment-439267547

Using Blazor Server Side From time to time Blazor throws the following error: No element is currently associated with component {ComponentId}

The error is always thrown on the first load after a StateHasChanged, if you hard refresh the page the error doesn't happen anymore.

For me this is quite vague and it happends for no certain reason, only from time to time.

SteveSandersonMS commented 6 years ago

This isn't a known issue, so if you have any way to reproduce it, we'd definitely want to fix it.

I can't really take any action on this right now because I've never seen this happen so have no clue about what might cause it. It's possibly something unique to your app, but we'd know more if there was a repro.

If you remove a surrounding <div> from the page, the error is gone.

Can you clarify this point? Is there some code sample you could post that shows it with the <div> that seemingly causes this problem?

SteveSandersonMS commented 6 years ago

Thanks for confirming!

It sounds like this is not a bug, but if you have a code sample to share that triggers the error, I could give a more precise answer.

vertonghenb commented 6 years ago

Issue is actually still unresolved, on unpredictable intervals I get the following error message:

Uncaught Error: No element is currently associated with component 944
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)

I wonder if it's possible to debug this sort of stuff. because I currently have no idea what component has the id 944

Codebase is pretty large, but I can do a VS Live Share if you'd like.

vertonghenb commented 5 years ago

ban

danroth27 commented 5 years ago

@vertonghenb For us to investigate we're going to need steps to reproduce the issue. Is there a way you can trim down your app to just the code that causes the problem?

vertonghenb commented 5 years ago

@danroth27 I'd love to give some reproduction steps but unfortunately I have no idea how to reproduce the issue, sometimes the error hardly shows up, sometimes it does more frequently. It happends after an async (await) load of data and navigating to another component the components takes a delegate functions Func<string, int, Task<List<T>>> as parameter. The issue is logged to get some knowledge of how to get a "dump" to see where the issue is thrown (in which component or function).

danroth27 commented 5 years ago

@SteveSandersonMS Might this be related at all to https://github.com/aspnet/Blazor/pull/1651?

SteveSandersonMS commented 5 years ago

@danroth27 I don't think so.

This issue implies that somehow it's possible to re-render a component after it's already been disposed (or that the initial attempt to add the component failed on the JS side, though I don't see how). That shouldn't be possible, and we have a test to back this up (that after disposal, re-render attempts will be skipped), but apparently there is some unanticipated timing-based way of doing that. If we had a repro I'm sure it would be quick to track down, but without one it's difficult to even start looking.

vertonghenb commented 5 years ago

@SteveSandersonMS I invited you to the Repository where the App is hosted, since the error is all over the place, I can't pin-point it. At a certain point I even changed every async code with sync.(not anymore though) then the error doesn't show up anymore so I believe it's related to async and timing. The instructions to reproduce the error are in the readme of the repo.

vertonghenb commented 5 years ago

@SteveSandersonMS , related to https://github.com/aspnet/Blazor/pull/1666 ?

vertonghenb commented 5 years ago

@SteveSandersonMS @danroth27 Using the 0.7.0-preview release: Well I can say, something changed in 0.7.0-preview. After the 0.7.0 release it now happends for all the components that should be rendered (it used to be only 1 error message, now there are plenty), the issue occurs on the OnInitAsync function which is basically a async Task to return a List<T>.

Task<List<T>> GetIndexAsync(string searchTerm, int take = 50);

When the code is not async, the error never occurs, so I'm pretty confident it's a timing issue.

Code that triggers this:

@page "/customers"
@using Ecocolors.Domain.Models.Stakeholders
@inject ICustomerManager CustomerManager
@inject IFormHandler FormHandler

<MPage Title="Klanten" Icon=@EIcon.EC_Customer>
    <Actions>
        <MButton Icon=@EIcon.LA_Plus State=@EState.Success OnClick=@((e) =>FormHandler.ShowCreateForm<Forms.Mutate>()) />
    </Actions>
    <Body>
        <MPortlet >
            <Content>
                <MToolBar SearchTerm="@_searchTerm" OnChanged="@OnSearchTermChange"/>
                <MTable TItem="Customer" Items="@_customers" IsLoading="@_isLoading">
                    <Header>
                        <th>Actief</th>
                        <th>Nummer</th>
                        <th>BTW Nr.</th>
                        <th>Naam</th>
                        <th>Adres</th>
                    </Header>
                    <Row Context="customer">
                        <td><MEnabledBadge IsEnabled=@customer.Enabled /></td>
                        <td>@customer.Sequence</td>
                        <td>@customer.VATNumber</td>
                        <td><MLink Url=@($"customers/{customer.Id}") Text=@customer.Name /></td>
                        <td>@customer.Headquarter?.Address?.DisplayName</td>
                    </Row>
                </MTable>
            </Content>
        </MPortlet>
    </Body>
</MPage>

@functions{
    private IReadOnlyList<Customer> _customers = new List<Customer>();
    private bool _isLoading = true;
    private string _searchTerm = string.Empty;
    private int _amount = 50;
    protected async override Task OnInitAsync()
    {
        _customers = await CustomerManager.GetIndexAsync(_searchTerm);
        _isLoading = false;
    }
    private async Task OnSearchTermChange(string term)
    {
        if (_isLoading)
            return;
        _isLoading = true;
        _searchTerm = term;
        StateHasChanged();
        _customers = await CustomerManager.GetIndexAsync(_searchTerm, _amount);
        _isLoading = false;
        StateHasChanged();
    }
}

On The Server:

Ecocolors.Server> System.AggregateException: One or more errors occurred. (Error: No element is currently associated with component 166) ---> Microsoft.AspNetCore.Blazor.Browser.Rendering.RemoteRendererException: Error: No element is currently associated with component 166
Ecocolors.Server>    --- End of inner exception stack trace ---
Ecocolors.Server> ---> (Inner Exception #0) Microsoft.AspNetCore.Blazor.Browser.Rendering.RemoteRendererException: Error: No element is currently associated with component 166<---
[... a few dozen more.]

On The Client:

blazor.server.js:38 Uncaught Error: No element is currently associated with component 536
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
03:26:22.373 blazor.server.js:38 Uncaught Error: No element is currently associated with component 537
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
03:26:22.503 blazor.server.js:38 Uncaught Error: No element is currently associated with component 536
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
03:26:22.504 blazor.server.js:38 Uncaught Error: No element is currently associated with component 538
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
03:26:22.504 blazor.server.js:38 Uncaught Error: No element is currently associated with component 539
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
03:26:22.504 blazor.server.js:38 Uncaught Error: No element is currently associated with component 540
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
03:26:22.504 blazor.server.js:38 Uncaught Error: No element is currently associated with component 541
    at e.updateComponent (blazor.server.js:23)
    at Object.t.renderBatch (blazor.server.js:16)
    at e.<anonymous> (blazor.server.js:38)
    at blazor.server.js:16
    at Array.forEach (<anonymous>)
    at e.invokeClientMethod (blazor.server.js:16)
    at e.processIncomingData (blazor.server.js:16)
    at e.connection.onreceive (blazor.server.js:16)
    at WebSocket.i.onmessage (blazor.server.js:16)
[... a few dozen more.]
vertonghenb commented 5 years ago

@danroth27 After a month of struggling... I finally reproduced the issue on a smaller app. It doesn't look that bad in the smaller application but bear in mind that on a more complex application the issue is thrown a lot more and makes Razor Components highly unstable and basically unusable(you don't want the user to have to refresh the app every 5 minutes).

The repository where the app is hosted can be found here: https://github.com/vertonghenb/Blazor-ComponentId The app is also hosted on azure, to make sure it's not a "on my machine problem" and can be found here: https://beerhallserver20181116035757.azurewebsites.net/

Version: ASP.NET Core 2.1.1 with EF Core (SQL Lite). Blazor Server Side running at 0.7.0.

2 pages Customer.Index.cshtnl and Brewers.Index.cshtml were added to the default template and some small components which are used in the MainLayout.cs. The pages fetches data using the BrewerManager.cs and CustomerManager.cs (basically a Repository pattern) using EF Core and a SQL Lite data provider. The call is async and awaited in the OnInitAsync function of the pages.

If you start clicking around in the navigating bar (like a maniac, I really mean like a maniac) navigating between multiple pages (even using the fetch data and counter pages, it can take up to 20-30+ navigations). You'll get the following error messages in the console, then the user has to refresh the browser.

This approach is only to reproduce the error, in my main app it's just 1-2 navigation and using the app like a normal person would.

Blazor-Bug-VS Blazor-Bug

If the data fetching logic is synchronous the error is never presented, but gives a rather annoying user experience.

aaronsmithuk commented 5 years ago

I updated my server side blazor app from 0.6 to 0.7 today, and have started to get loads of the stated error: "Uncaught Error: No element is currently associated with component". It's happening all over the app (I get hundreds of error messages). Also, changes to the dom are now visually obvious, the page content flashes as it is replaced, whereas in 0.6 it updated smoothly.

TheRubble commented 5 years ago

Also started to see this problem since the update to 0.7.0. Not noticed the DOM issues with redraw. It seems that once a page suffers from this issue there are 2 ways to resolve it. Navigate to another page within the application and back, or a full page refresh. I did think it was something to do with timing but it's not.

This issue is happening on the most basic of pages.

@page "/simple-page"
<h1>Waiting for API implementation.</h1>

As mentioned it seems to be async related. I have a navigation component included in the master layout which async loads data.

DeanRoddey commented 5 years ago

We are also experiencing this suddenly after 0.7. It also is to do with an await in an after render async callback. It'll work a for a while, then suddenly one time the elementref is not set. And since you (apparently) can't even test an elementref to see if its good, it's tough to even work around. If you don't do something to prevent re-render after the error, it goes off into a loop, as above.

MarkStega commented 5 years ago

Another +1 from the same team as Dean above, but on an unrelated Blazor project. I'd say this was occaisional in 0.6.0 and could never be pinned down but happens with regularity on 0.7.0

vertonghenb commented 5 years ago

@aaronsmithuk , @TheRubble , @DeanRoddey , @MarkStega Some repro’s?

DeanRoddey commented 5 years ago

I think that this newer issue is probably the same underlying thing?

https://github.com/aspnet/Blazor/issues/1700

The suggestion there is that maybe on after render is getting triggered too early sometimes, before elementrefs are set.

vertonghenb commented 5 years ago

@DeanRoddey There is no elementref involved in the codebase.

vertonghenb commented 5 years ago

Since multiple applications are having this issue, can we mark it as a bug?

SteveSandersonMS commented 5 years ago

Sure. I've no doubt there's a real bug here. I strongly expect it will vanish when we deal with #5639 (though if it doesn't, obviously we'll have to track down the cause).

Gaulomatic commented 5 years ago

I am getting this error as well. I have declared multiple components (entrypoints) in the Startup.cs:

app.AddComponent<GetInvolved>("app-1"); app.AddComponent<ActionCallList>("app-2");

I include them on different locations on the website. However, this makes this error appear. Only if I include every tag of all declared components, the error does not occur (It does at some point if navigation events take place, but in my case this isn't happening). May be this helps to track down the cause.

gulbanana commented 5 years ago

i'm experiencing this in similar circumstances. i have a repro if that's useful - an app which breaks very quickly when run under SSR/razor components. i can share it but not publically

gulbanana commented 5 years ago

I'm currently using a workaround - I have a custom version of blazor.server.js where the renderer gives up trying to apply the edit and just returns, rather than throwing an error which will break the websocket connection. this isn't suitable for production, since it still means that some component just doesn't update and you have to try the state change again, but it's ok for demos and prototyping

CobraCalle commented 5 years ago

Hello,

I've got this error too, but I think the problem is another than discussed until now…

We are developing a blazor version of our 3D product configuration application at the moment and we use xml3d to build the scene in html with blazor (works like a charm by the way :-) ). Here we define the required materials first and later we reference the materials in the geometries... at some point of the development we had the situation that some geometries were rendered with the wrong material or with no material... but the material elements where correct. So we hat a look how the material elements where changed while configuring (for example changing the color of the product).

And I think what we saw is the underlying problem here: When we added a material that was not the last in the material list (we sorted the elements by their id), the DOM was correctly changed… BUT the "instances" where changed mixed up… example…

< Material id="a" src="x"/> < Material id="c" src="y"/>

Then we add:

Result: < Material id="a" src="x"/> < Material id="b" src="z"/> < Material id="c" src="y"/>

On the first look, that is correct… BUT the former material "c" was changed to "b" and a new element with id "c" was added (you can see this in dev mode of chrome)… and that was the problem! We fixed it by making sure that we only add new elements to the end and never remove elements (in this example a,c,b) and that works. But of course this only works in this special scenario and we have the lots of problems with "no elements etc." too, but I think this gives us an interesting hint, why the event handles stop working…

Lets adapt the scenario from above to an other sample... When we have a list of components that are clickable…

< div onclick="handler (click component 1)">Product A< /div> < div onclick="handler (click component 2)">Product B< /div>

now we remove product B and add Product C... then we expect that the html-element of product B is removed and a new element for product C is created… but that is not the case… it "updates" the existing element for product B to match the required element for product C. And in this case the event handler IS NOT updated to macht the event handler for product C... result:

< div onclick="handler (click component 1)">Product A< /div> < div onclick="handler (click component 2)">Product C< /div>

When you click on product C the server creates an exception "no element assigned to 2" because the sever "thinks" the element for product B (2) was removed and a new for product C (3) was created… but that is not the case.

When you now create a button that toggles the rendering of the product list and click it to remove all elements and click it again to rerender the list, everything is working again…

I hope this helps to get rid of this annoying bug…

Carl

SteveSandersonMS commented 5 years ago

@CobraCalle Your issue sounds unrelated to the one being originally reported here. I think your issue is that you need to preserve DOM element identity through edits because of the 3rd party library that's also interacting with the DOM. This requirement is handled by specifying key, however it's not yet implemented (tracked in #5455). Until we implement key, you'll need to continue using your current workaround.

DeanRoddey commented 5 years ago

You know, thinking about this just now as it was happening to me again... I wonder if it's as simple as just not reliably getting rid of element/component references when the things referenced go away. Given that, for us, it always happens after we invoke a modal, and then render those bits away when the modal is dismissed. The stuff is obviously gone, because it doesn't get drawn anymore and StateHasChanged has to be called to make that happen, but then we get the problem after that in certain subsequent popups.

It's as though some internal refs to the things that got rendered away are still there.

DaleCam commented 5 years ago

Ok it took a lot of elimination, but for me - I can replicate this Issue as soon as I inject a HttpClient in my page. I dont even have to use it. Just inject it: [Inject] private HttpClient Http { get; set; } And as soon as I take this line out, the page works again. I hope that helps narrow it down! (It also explains why the Server Side Template Project still works as none of the pages use HTTPClient...)

DaleCam commented 5 years ago

Ok it took a lot of elimination, but for me - I can replicate this Issue as soon as I inject a HttpClient in my page. I dont even have to use it. Just inject it: [Inject] private HttpClient Http { get; set; } And as soon as I take this line out, the page works again. I hope that helps narrow it down! (It also explains why the Server Side Template Project still works as none of the pages use HTTPClient...)

Further to this its actually when i simply Inject ANYTHING on the page. I created a skeleton class, injected it into my page, and I got the "No element is currently associated with component {id}" error. When I remove the inject, the page loads correctly again. (This is only on server side - client side blazor works fine). Which now has me very confused as for some reason the Template Server Side Project injects a service in the FetchData Page and its working fine. Same version of blazor and .net core... im stumped!

DaleCam commented 5 years ago

I was just able to solve this (for my project anyway) by following the fantastic idea in this git: https://github.com/Suchiman/BlazorDualMode (Step 2 alone fixes it for me, but i love the url switch idea so i did the whole shabang)

vertonghenb commented 5 years ago

Seems to be fixed in Preview-2

dynamiclynk commented 5 years ago

I received this error because I was trying to @ inject the wrong type and this was the general error that was thrown instead of a relevant error relating to finding the service in the collection\container.

This happened with 3.0.0-preview8.19405.7

Also when this occurred I could not step into client debugger since this is happening in @ inject