Debugger stepping incorrect in async method: execution flow jumps to `else` block after `return`
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
### Description
I have encountered an issue with the debugger stepping behavior in an `async` method. When the code successfully executes a `return` statement inside a `try` block (which is nested within an `if` block), the debugger step-over (F10) action visually jumps the instruction pointer into the `else` block of the outer `if` statement.
Despite the debugger highlighting the code inside the `else` block, the method actually returns the correct value (from the `if` block), indicating that the compiled code execution is likely correct, but the sequence points or debugger information generated is misleading.
This behavior is confusing as it suggests that the fallback logic in the `else` block is being executed when it is not.
### Reproduction Steps
I have attached a minimal reproduction project.
1. Open the attached solution.
2. Navigate to the `ShortenAsync` method (in `ShortLinkService.cs`).
3. Set a breakpoint on the line:
```csharp
var resultUrl = await AddOrGetShortUrlFromDbAsync(dbContext, newLink);
```
4. Start debugging.
5. When the breakpoint is hit, Step Over (F10).
**Code snippet for context:**
```csharp
if (urlShortenerProviderResult.Success)
{
// ... object initialization ...
try
{
var resultUrl = await AddOrGetShortUrlFromDbAsync(dbContext, newLink); // <--- Breakpoint here
return resultUrl; // <--- Step Over this
}
catch (Exception e)
{
// ... logging ...
return shortUrl;
}
}
else
{
// Debugger jumps HERE after the return above
_logger.LogError("Can't get a short url from the provider...");
return longUrl;
}
```
[DotnetBugRepro-master.zip](https://github.com/user-attachments/files/24179096/DotnetBugRepro-master.zip)
### Expected behavior
After stepping over `return resultUrl;`, the debugger should exit the method or move to the closing brace of the method context. It should not highlight any lines inside the `else` block.
### Actual behavior
The debugger execution pointer jumps to the `else` block (e.g., to the logging statement or the `return longUrl` line), creating the false impression that the `if (Success)` check failed or that the flow fell through.
### Regression?
_No response_
### Known Workarounds
_No response_
### Configuration
.NET 10.0.101 x64
Windows 11
x64
Console App
### Other information
_No response_
Contributor guide
Research direction
Start with the attached DotnetBugRepro project and inspect ShortLinkService.cs, especially ShortenAsync and its async try/return inside the if block. Run the reproduction on .NET 10.0.101, step over the marked await and return, and compare the debugger location with the actual returned value; done means the pointer does not highlight the outer else block after the successful return.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100