Quick answer: A Blueprint read a reference to an actor or component that has already been destroyed. The variable still points at it until garbage collection runs. Guard the access with Is Valid, clear the reference when the target is destroyed (bind to On Destroyed or End Play), and clear timers and latent actions that can fire after their owner is gone.

UE5 replaced many of the old “Accessed None” messages with this more specific one. It means the variable is not empty; it points at something that was destroyed. That is a timing bug, and the error message tells you exactly which node, graph and Blueprint to look at.

The exact error

In the Message Log after a Play-in-Editor session, or in the Output Log:

Blueprint Runtime Error: "Attempted to access BP_Enemy_C_3 via property TargetEnemy, but BP_Enemy_C_3 is not valid (pending kill or garbage)". Node:  Get Actor Location Graph:  EventGraph Function:  Execute Ubergraph BP Player Blueprint:  BP_Player

Read it right to left: in BP_Player's EventGraph, the Get Actor Location node used the variable TargetEnemy, which still referenced BP_Enemy_C_3 after that enemy was destroyed. Click the node link in the Message Log to jump to it.

Why the reference is not None

Calling Destroy Actor marks the actor for destruction; it does not reach into every Blueprint and clear variables that point at it. Until garbage collection runs, the variable still holds the old object, now flagged as pending kill or garbage. Blueprint nodes that read from it report this error, and C++ code that dereferences it without checking can crash.

Typical ways to get there:

Fix 1: guard every stored reference with Is Valid

Before you use a reference that was stored earlier, check it. In Blueprints, use the Is Valid macro (the one with Is Valid / Is Not Valid exec pins), or a validated get by right-clicking the variable getter and choosing Convert to Validated Get. Is Valid returns false for both empty references and pending-kill objects, which a plain != None comparison does not.

In C++:

if (IsValid(TargetEnemy))
{
    const FVector Loc = TargetEnemy->GetActorLocation();
    // ...
}

Fix 2: clear the reference when the target dies

Checking hides the symptom; clearing the reference fixes the state. When you store a reference, bind to the target's On Destroyed event (or On End Play) and set your variable back to None in the handler. For arrays, remove the element in the same handler.

In C++, prefer a weak pointer for references you do not own, so a destroyed target reads as null:

UPROPERTY()
TWeakObjectPtr<AEnemyCharacter> TargetEnemy;

if (AEnemyCharacter* Enemy = TargetEnemy.Get())
{
    Enemy->ApplyDamage(10.f);
}

Fix 3: stop timers and delays from outliving their actors

Timers keep running after the logic that needed them is over. Store the timer handle and clear it in End Play, or clear everything the actor owns:

void AMyTurret::EndPlay(const EEndPlayReason::Type Reason)
{
    GetWorldTimerManager().ClearAllTimersForObject(this);
    Super::EndPlay(Reason);
}

In Blueprints, use Clear and Invalidate Timer by Handle in End Play. For Delay nodes, check Is Valid on anything you use after the delay, because the world may have changed while it waited.

Finding the source when it is intermittent

When it only happens in long sessions

Timing bugs like this are the ones that survive testing: they depend on what died when. In a packaged build, a C++ path that dereferences the same stale pointer becomes a crash. Bugnet's Unreal SDK files fatal errors and ensures with recent log output and the player's hardware, grouped by signature with an occurrence count, so you can see how often it happens and which build introduced it.

Frequently asked questions

What does “pending kill or garbage” mean in Unreal?

The object was destroyed or marked for garbage collection, but a variable still points at it. Reading from it in a Blueprint produces this runtime error.

How do I fix “Attempted to access ... but it is not valid”?

Check the reference with Is Valid before using it, clear the variable when the target is destroyed, and clear timers and delays in End Play so they do not fire after their owner is gone.

Why doesn’t comparing to None catch destroyed actors?

A destroyed actor is not None until garbage collection clears the reference. Is Valid checks both cases, which is why it is the right test.

If you store a reference to something you did not spawn, plan for the moment it disappears.