---
uid: AK1005
title: Akka.Analyzers Rule AK1005 - "Must close over `Sender` or `Self`"
---

# AK1005 - Warning

When accessing `Sender` or `Self` inside a lambda expression passed as an asynchronous method argument, you must always close over `Sender` or `Self` to ensure that the property is captured before the method is invoked, because there is no guarantee that asynchronous context will be preserved when the lambda is invoked inside the method.

## Cause

Akka.NET tries its best to preserve asynchronous context if asynchronous codes were to run inside the actor. However, there are times where this is impossible to enforce, especially when a code that accesses variables that were thread execution specific such as the actor `Context`, `Sender`, and `Self` is being invoked outside the actor threading context.

For example, lets assume that you're using an asynchronous third party API package that invokes a callback when it completes its operation:

```csharp
using System;
using System.Threading.Tasks;

namespace ThirdPartyApi;

public sealed class JobManager
{
    public async Task SubmitJobAsync(string job, Func<Task> asyncCallback)
    {
        // This breaks asynchronous context
        await ConnectToServer().ConfigureAwait(false); 
        // other codes here
        
        await asyncCallback();
    }
    
    private async Task ConnectToServer()
    {
        // codes here
    }
}
```

In the code above, the `ConfigureAwait(false)` call breaks the asynchronous context before the callback method were invoked. If this third party API code were to be used inside Akka.NET and `Context`, `Sender`, or `Self` were accessed inside the callback, we will see an error during runtime:

```csharp
using System;
using System.Threading.Tasks;
using Akka.Actor;
using ThirdPartyApi;

namespace MyApplication.Actors;

public sealed class MyActor : ReceiveActor
{
    private readonly JobManager _jobManager = new();
    
    public MyActor()
    {
        ReceiveAsync<string>(async job => {
            _jobManager.SubmitJobAsync(job, async () => 
            {
                // This callback will not work
                Context.Sender.Tell($"{job} submitted.", Self);
            })
        });
    }
}
```

```text
NotSupportedException
There is no active ActorContext, this is most likely due to use of async operations from within this actor.
  at MyApplication.Actors.MyActor`1<>c__DisplayClass48_0.<<InvokeTestMethodAsync>b__1>d.MoveNext() in \src\MyApplication.Actors\MyActor.cs:line 16
```

## Resolution

While working with a third party API, it is most likely that you will not have a way to modify their codes to make them compatible with your asynchronous flow.  To avoid this entire category of problem, we should close over any access to `Sontext.Self`, `Context.Sender`, `Self`, and `Sender` property in a local variable.

For the non-working example above, we can fix it by modifying our code:

```csharp
using System;
using System.Threading.Tasks;
using Akka.Actor;
using ThirdPartyApi;

namespace MyApplication.Actors;

public sealed class MyActor : ReceiveActor
{
    private readonly JobManager _jobManager = new();
    
    public MyActor()
    {
        ReceiveAsync<string>(async job => {
            // Store Context.Sender and Self inside local variable
            var sender = Context.Sender;
            var self = Self;
            
            _jobManager.SubmitJobAsync(job, async () => 
            {
                // Use local variables instead of accessing Context directly
                sender.Tell($"{job} submitted.", self);
            })
        });
    }
}
```
