Quick answer: Apply [DeallocateOnJobCompletion] to a NativeArray on at most one job in a dependency chain — usually the last. Anything reading the array after completion errors out. Prefer explicit .Dispose() for clarity.

Job runs, completes, you try to read the result, and Unity throws “The Allocator label is not valid.” The buffer was freed before you got to it — almost always because of a misplaced DeallocateOnJobCompletion attribute.

The Symptom

Errors like “The NativeArray has not been allocated, it has been disposed, or its safety handle has expired.” The job ran successfully; the read happens after.

What Causes This

The [DeallocateOnJobCompletion] attribute frees the NativeArray when the job is done. If you intend to read the buffer on the main thread after the job completes, you must not deallocate it during the job. The attribute should be on buffers the job uses internally and that no one else needs after.

The Fix Patterns

Pattern 1: Explicit Dispose. Most reliable.

var data = new NativeArray<float>(1024, Allocator.TempJob);

var job = new MyJob { data = data };
var handle = job.Schedule();
handle.Complete();

// Read on main thread before disposing
Debug.Log($"first: {data[0]}");

data.Dispose();

Pattern 2: DeallocateOnJobCompletion for fire-and-forget.

[BurstCompile]
public struct MyJob : IJob
{
    [DeallocateOnJobCompletion]
    public NativeArray<float> scratch;   // freed by job, never read after

    public NativeArray<float> result;       // not freed; main thread reads after

    public void Execute() { ... }
}

Use Deallocate only on buffers the main thread will not touch. Output buffers must be disposed manually after read.

Chained Jobs

If Job A schedules with a buffer, Job B depends on A and uses the same buffer, only B may DeallocateOnJobCompletion that buffer. Putting it on A frees the buffer before B runs.

var data = new NativeArray<float>(100, Allocator.TempJob);

var a = new JobA { data = data };
var handleA = a.Schedule();

var b = new JobB { data = data };
var handleB = b.Schedule(handleA);   // depends on A

handleB.Complete();
data.Dispose();                       // safe: B finished

Allocator Choice

The error “Allocations of TempJob may not survive longer than 4 frames” comes from forgetting to Complete + Dispose within the budget.

Verifying

Run with Job Safety Checks on (default in Editor). The first frame after a misuse, you get the precise error and a stack trace pointing at the access. Disable safety checks only for measured benchmarks.

“Deallocate where the buffer dies. Dispose explicitly otherwise. Safety checks tell you the rest.”

Related Issues

For Burst managed allocation warnings, see Burst BC1006. For NativeArray leaks, see NativeArray leak.

Free where the buffer dies. Read before. Dispose explicit.