Cysharp/UniTask · error · InvalidOperationException
Detected invalid initialization(use 'default'), only to crea
Error message
Detected invalid initialization(use 'default'), only to create from StartNew().
What it means
Thrown by ValueStopwatch.ElapsedTicks when startTimestamp is 0, meaning the stopwatch was created via 'default(ValueStopwatch)' or 'new ValueStopwatch()' instead of ValueStopwatch.StartNew(). ValueStopwatch is a struct; its zero-initialized state is invalid because timestamp 0 is indistinguishable from 'never started'. The IsInvalid property exposes this check.
Source
Thrown at src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs:29
public static ValueStopwatch StartNew() => new ValueStopwatch(Stopwatch.GetTimestamp());
ValueStopwatch(long startTimestamp)
{
this.startTimestamp = startTimestamp;
}
public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
public bool IsInvalid => startTimestamp == 0;
public long ElapsedTicks
{
get
{
if (startTimestamp == 0)
{
throw new InvalidOperationException("Detected invalid initialization(use 'default'), only to create from StartNew().");
}
var delta = Stopwatch.GetTimestamp() - startTimestamp;
return (long)(delta * TimestampToTicks);
}
}
}
}View on GitHub (pinned to ceac8d6946)
Solutions
- Always create via ValueStopwatch.StartNew() — never use default or new().
- Check sw.IsInvalid before accessing Elapsed if the stopwatch may not have been initialized.
- Initialize fields at declaration: private ValueStopwatch sw = ValueStopwatch.StartNew();
Example fix
// before ValueStopwatch sw; // ... sw never assigned ... var elapsed = sw.Elapsed; // throws // after var sw = ValueStopwatch.StartNew(); var elapsed = sw.Elapsed; // ok
Defensive patterns
Strategy: validation
Validate before calling
if (stopwatch.IsInvalid)
{
stopwatch = ValueStopwatch.StartNew();
}
var elapsed = stopwatch.Elapsed; Type guard
static bool IsStarted(ValueStopwatch sw) => !sw.IsInvalid;
Prevention
- Always initialize with ValueStopwatch.StartNew() — never default or new().
- Initialize fields at declaration or in the constructor.
- Check IsInvalid before accessing Elapsed if conditional initialization is possible.
When it happens
Trigger: Declaring a ValueStopwatch field or local with default initialization (no assignment) and then accessing .Elapsed or .ElapsedTicks. Using 'new ValueStopwatch()' instead of StartNew(). Forgetting to initialize a stopwatch before first use.
Common situations: A field-level ValueStopwatch that is conditionally started but accessed unconditionally. Copying a stopwatch struct by value after it was zero-initialized. A lazy-initialized field where the access path doesn't check IsInvalid.
Related errors
- Not yet completed.
- Target PlayerLoopSystem does not found. Type:
- Target playerLoopTiming is not injected. Please check Player
AI-assisted analysis of Cysharp/UniTask@ceac8d6946 (2026-08-13).
Data as JSON: /api/errors/209936d1cdcfaeaf.
Report an issue: GitHub.