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
- Why the reference is not None
- Fix 1: guard every stored reference with Is Valid
- Fix 2: clear the reference when the target dies
- Fix 3: stop timers and delays from outliving their actors
- Finding the source when it is intermittent
- When it only happens in long sessions
- Related problems
- Frequently asked questions
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:
- Storing the current target, interactable or pickup in a variable and using it on a later tick after something else destroyed it.
- A Delay or timer that fires after the actor that started it, or the actor it refers to, was destroyed.
- Arrays of actors (spawned enemies, projectiles) that are never pruned.
- Level streaming unloading an actor that another level still references.
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
- Turn on Break on Exceptions (search for it in Editor Preferences), so PIE pauses on the failing node with the call stack and variable values visible.
- Search the Blueprint for every Set of the variable named in the error; one of them is storing an actor that gets destroyed elsewhere.
- If it happens only in multiplayer, check whether the client is holding a reference to an actor the server destroyed.
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.
Related problems
- How to Fix an Access Violation Crash in Unreal Engine
- How to Fix “Ensure condition failed” in Unreal Engine
- How to Fix an Unreal Blueprint Infinite Loop Crash
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.