{"record":{"id":"209936d1cdcfaeaf","repo":"Cysharp/UniTask","slug":"detected-invalid-initialization-use-default-on","errorCode":null,"errorMessage":"Detected invalid initialization(use 'default'), only to create from StartNew().","messagePattern":"Detected invalid initialization\\(use 'default'\\), only to create from StartNew\\(\\)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs","lineNumber":29,"sourceCode":"\n        public static ValueStopwatch StartNew() => new ValueStopwatch(Stopwatch.GetTimestamp());\n\n        ValueStopwatch(long startTimestamp)\n        {\n            this.startTimestamp = startTimestamp;\n        }\n\n        public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);\n\n        public bool IsInvalid => startTimestamp == 0;\n\n        public long ElapsedTicks\n        {\n            get\n            {\n                if (startTimestamp == 0)\n                {\n                    throw new InvalidOperationException(\"Detected invalid initialization(use 'default'), only to create from StartNew().\");\n                }\n\n                var delta = Stopwatch.GetTimestamp() - startTimestamp;\n                return (long)(delta * TimestampToTicks);\n            }\n        }\n    }\n}","sourceCodeStart":11,"sourceCodeEnd":37,"githubUrl":"https://github.com/Cysharp/UniTask/blob/ceac8d6946b1125fe782cd171fbcb245b567dbf9/src/UniTask/Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs#L11-L37","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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();"],"exampleFix":"// before\nValueStopwatch sw;\n// ... sw never assigned ...\nvar elapsed = sw.Elapsed; // throws\n\n// after\nvar sw = ValueStopwatch.StartNew();\nvar elapsed = sw.Elapsed; // ok","handlingStrategy":"validation","validationCode":"if (stopwatch.IsInvalid)\n{\n    stopwatch = ValueStopwatch.StartNew();\n}\nvar elapsed = stopwatch.Elapsed;","typeGuard":"static bool IsStarted(ValueStopwatch sw) => !sw.IsInvalid;","tryCatchPattern":null,"preventionTips":["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."],"tags":["stopwatch","struct-default","misuse","initialization"],"backgroundTag":null,"analyzedSha":"ceac8d6946b1125fe782cd171fbcb245b567dbf9","analyzedAt":"2026-08-13T19:16:39.025Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}