bugsnag-unity
bugsnag-unity copied to clipboard
InvalidOperationException Collection was modified; enumeration operation may not execute
Describe the bug
I'm seeing exceptions coming from BugsnagUnity.Client
.
Steps to reproduce
I couldn't reproduce when the exception is being thrown, so can't give exact stepts.
Environment
- Bugsnag version: 7.7.1 bugsnag-unity-upm-edm4u version.
- Unity version: 2021.3.28f1
- iOS/Android/macOS/Windows/browser version:
- simulator/emulator or physical device: physical device - Android. Not sure about iOS.
- Initializing bugsnag via a Unity GameObject or in code?: via GameObject
- Player Settings:
- Scripting backend (Mono or IL2CPP): IL2CPP
- API compatibility level for .NET:
- Stack Trace level for all error types (None/ScriptOnly/Full): Provided
Example Repo
- [ ] Create a minimal repository that can reproduce the issue
- [ ] Link to it here:
Example code snippet
# (Insert code sample to reproduce the problem)
Error messages:
InvalidOperationException Collection was modified; enumeration operation may not execute.
<00000000000000000000000000000000> System.Collections.Generic.List`1+Enumerator[T].MoveNext()
<00000000000000000000000000000000> BugsnagUnity.Client.NotifyOnMainThread(BugsnagUnity.Payload.Error[] exceptions, BugsnagUnity.Payload.HandledState handledState, System.Func`2[T,TResult] callback, System.Nullable`1[T] logType)
<00000000000000000000000000000000> BugsnagUnity.Client+<>c__DisplayClass56_0.<Notify>b__0()
<00000000000000000000000000000000> BugsnagUnity.MainThreadDispatchBehaviour+<ActionWrapper>d__6.MoveNext()
<00000000000000000000000000000000> UnityEngine.SetupCoroutine.InvokeMoveNext(System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress)
<00000000000000000000000000000000> BugsnagUnity.MainThreadDispatchBehaviour.Update()
InvalidOperationException Collection was modified; enumeration operation may not execute.
<00000000000000000000000000000000> System.Collections.Generic.List`1+Enumerator[T].MoveNextRare()
<00000000000000000000000000000000> System.Collections.Generic.List`1+Enumerator[T].MoveNext()
<00000000000000000000000000000000> BugsnagUnity.Client.NotifyOnMainThread(BugsnagUnity.Payload.Error[] exceptions, BugsnagUnity.Payload.HandledState handledState, System.Func`2[T,TResult] callback, System.Nullable`1[T] logType)
<00000000000000000000000000000000> BugsnagUnity.MainThreadDispatchBehaviour+<ActionWrapper>d__6.MoveNext()
<00000000000000000000000000000000> UnityEngine.SetupCoroutine.InvokeMoveNext(System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress)
<00000000000000000000000000000000> BugsnagUnity.MainThreadDispatchBehaviour.Update()
It seems it is being thrown when the notify
is being called from different threads. Any thoughts?
Hi @gagbaghdas
Can you please share a copy of your BugSnag configuration and callback configurations, including any code snippets or screenshots that may aid in our investigation?
@clr182 sure. Here is my code:
using System;
using System.Collections.Generic;
using BugsnagUnity;
namespace MyNameSpace
{
public class BugsnagWrapper : MyInterface
{
private const string bugsangApiKey = "MySDKKey";
private bool initialized = false;
private bool userInitialized = false;
private ErrorReportingUserMainProperties userProperties;
private readonly Dictionary<string, object> customProperties = new();
public void Initialize(IContext context)
{
// Call this method if you don't want Bugsnag to be started automatically before first scene load
//InitializeBugsangManully();
}
/// <summary>
/// Starts Bugsnag Service manually
/// </summary>
private void InitializeBugsangManully()
{
if (!initialized)
{
var config = BugsnagSettingsObject.LoadConfiguration();
config.ApiKey = bugsangApiKey;
Bugsnag.Start(config);
initialized = true;
}
}
public void InitializeUser(ErrorReportingUserMainProperties userProperties)
{
if (userInitialized)
{
return;
}
this.userProperties = userProperties;
Bugsnag.SetUser(userProperties.UserId, string.Empty, string.Empty);
AddMetadata("user", userProperties.GetPropertiesDictionary());
userInitialized = true;
}
public void Notify(Exception ex)
{
bool BeforeNotify(BugsnagUnity.IEvent @event)
{
if(userProperties != null)
{
if (!string.IsNullOrEmpty(userProperties.UserId) && @event.GetUser().Id != userProperties.UserId)
{
Bugsnag.SetUser(userProperties.UserId, string.Empty, string.Empty);
}
AddMetadata("user", userProperties.GetPropertiesDictionary());
}
AddMetadata("customProperties", customProperties);
return true;
}
Bugsnag.AddOnError(BeforeNotify);
Bugsnag.Notify(ex);
Bugsnag.RemoveOnError(BeforeNotify);
}
private void AddMetadata(string section, Dictionary<string, object> addingMetadata)
{
if (addingMetadata.Count == 0)
{
return;
}
if (Bugsnag.GetMetadata(section) == null || Bugsnag.GetMetadata(section).Count == 0)
{
Bugsnag.AddMetadata(section, addingMetadata);
return;
}
foreach (var metaData in addingMetadata)
{
if (Bugsnag.GetMetadata(section, metaData.Key) == null)
{
Bugsnag.AddMetadata(section, metaData.Key, metaData.Value);
continue;
}
if (Bugsnag.GetMetadata(section, metaData.Key) != metaData.Value)
{
Bugsnag.ClearMetadata(section, metaData.Key);
Bugsnag.AddMetadata(section, metaData.Key, metaData.Value);
}
}
}
public void Restart()
{
initialized = false;
}
public void SetCustomProperty(string key, string value)
{
customProperties[key] = value;
}
}
}
And here is the configuration:
Thanks