From InvalidOperationException to Insight: My AI Debugging Journey with .NET 9
Last Tuesday, I hit a familiar wall: System.InvalidOperationException: Collection was modified; enumeration operation may not execute. I was trying to optimize a legacy .NET 9 endpoint, iterating a list of active connections while a background task could add new ones. Classic race condition, but in a sprawling codebase, tracing the exact timing and interplay felt like untangling wet spaghetti. My usual approach of setting breakpoints and stepping through felt like it would take hours.
This particular bug pushed me over the edge. I've been cautiously optimistic about AI's role in dev workflows, but mostly for boilerplate code or documentation. Could it actually help with real, gnarly debugging? For two weeks, I decided to lean heavily into ai debugging dotnet tools, specifically focusing on how Claude Opus 4.7 and Visual Studio 2026's integrated AI features could speed up my ai bug fix cycle.
My First Forays (and Fumbles) with Claude Debugging C
My initial attempts at claude debug csharp were, frankly, a bit clunky. I'd paste the exception, maybe a few lines of code, and get back generic advice like "use ToList() before iterating" or "add locks." Useful, but not always the deep insight I needed for a specific context. My first major screw-up was feeding it too little context. I’d paste a method, but forget to include the calling code or the full stack trace. The AI, understandably, made assumptions that led me down a few rabbit holes.
What I ended up doing was taking a more structured approach. When I hit that InvalidOperationException, I grabbed the full stack trace, the problematic method, and any relevant class definitions. Then, I'd prompt Claude Opus 4.7 directly within Cursor 0.42+, which I’ve been using more lately for its integrated AI chat.
Here’s a simplified version of a prompt that finally got me somewhere:
I'm getting a System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
Here's the stack trace:
at System.Collections.Concurrent.ConcurrentQueue`1.GetEnumerator()
at MyNamespace.ConnectionManager.ProcessConnections() in C:\...\ConnectionManager.cs:line 45
at MyNamespace.BackgroundService.DoWork(CancellationToken cancellationToken) in C:\...\BackgroundService.cs:line 22
Here's the relevant code from ConnectionManager.cs:
public class ConnectionManager
{
private readonly ConcurrentQueue<Connection> _activeConnections = new ConcurrentQueue<Connection>();
public void AddConnection(Connection connection)
{
_activeConnections.Enqueue(connection);
}
public void ProcessConnections()
{
foreach (var connection in _activeConnections) // Line 45
{
// Process connection
if (connection.ShouldBeRemoved())
{
// This is where the issue might be - trying to remove while iterating.
// But ConcurrentQueue doesn't have a direct Remove.
}
}
}
}
The issue occurs on line 45. The `AddConnection` method can be called from multiple threads.
How can I safely iterate and potentially remove connections without causing this exception?
Claude’s response was surprisingly insightful, pointing out that even ConcurrentQueue iterators can throw this if the collection is modified during enumeration, and that direct removal isn't supported. It suggested a few patterns, but the one that stuck was using a snapshot or a producer-consumer pattern. This was a lightbulb moment for me, realizing the AI understood the nuances beyond just "use lock."
The Setup I Settled On for Rapid AI Bug Fixes
After a few days of trial and error, I found a workflow that significantly cut down my ai bug fix time. Instead of just pasting code, I now treat the AI as a highly knowledgeable, slightly context-blind colleague.
- Replicate (or Isolate): Get a minimal reproducible example or at least the exact failure scenario.
- Gather Context: Full stack trace, relevant code (including dependencies or interfaces), and a clear description of what I was trying to do.
- Prompt the AI: I've found that Claude Opus 4.7, particularly when given a good "System Prompt" (using MCP in Cursor or Copilot for Workspaces in VS 2026), provides the best results. I ask it to explain the root cause first, then suggest solutions, and finally provide a code example.
- Review and Implement: This is crucial. I never just copy-paste. The AI's suggestion is a starting point. I understand why it works, verify it, and then integrate it into my codebase.
For my InvalidOperationException, the AI nudged me towards a simple snapshot approach for processing, acknowledging that ConcurrentQueue isn't designed for mid-iteration removal. What I ended up with was something like this:
public class ConnectionManager
{
private readonly ConcurrentQueue<Connection> _activeConnections = new ConcurrentQueue<Connection>();
public void AddConnection(Connection connection)
{
_activeConnections.Enqueue(connection);
}
public void ProcessConnections()
{
// Take a snapshot of the current connections
var connectionsToProcess = _activeConnections.ToList(); // Safe snapshot
foreach (var connection in connectionsToProcess)
{
// Process connection
if (connection.ShouldBeRemoved())
{
// If removal is needed, re-enqueue only the ones that should remain
// or use a separate mechanism for removal (e.g., a "dead connections" queue)
// For this specific bug, simply not re-adding it effectively "removes" it from the next snapshot.
}
else
{
// If connection is still active and needs to be processed again,
// re-enqueue it or ensure it's handled by AddConnection if it's new.
// My actual fix involved moving to a ConcurrentDictionary for easier ID-based removal.
}
}
// For a ConcurrentQueue, if you need to "remove" items, you typically drain and re-populate.
// A better structure might be ConcurrentDictionary<Guid, Connection> for explicit removal.
// The AI's core insight was "don't modify the collection you're iterating."
}
}
This wasn't a direct "copy-paste" fix, but the AI pointed me to the fundamental issue and the common patterns. It saved me hours of stepping through code, letting me focus on the architectural implications of the fix. Your mileage may vary with the specific AI and prompt, but for ai debugging dotnet in a crunch, this worked wonders for me.
I'm still figuring out the best way to integrate AI into every debugging scenario, especially for subtle performance issues or highly domain-specific logic. But for common concurrency bugs or puzzling exceptions, it feels like I've gained a superpower.
If you've tried using Claude Opus 4.7 or similar AI tools for real-world ai debugging dotnet scenarios, especially in legacy C# projects, I'd love to hear what specific challenges you faced and how you overcame them.
Top comments (0)