{"record":{"id":"6bdc5997ca0b3c09","repo":"XINCGer/Unity3DTraining","slug":"non-normalized-timestamp-value","errorCode":null,"errorMessage":"Non-normalized timestamp value","messagePattern":"Non-normalized timestamp value","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/WellKnownTypes/TimestampPartial.cs","lineNumber":223,"sourceCode":"                // Use .NET's formatting for the value down to the second, including an opening double quote (as it's a string value)\n                DateTime dateTime = UnixEpoch.AddSeconds(seconds);\n                var builder = new StringBuilder();\n                builder.Append('\"');\n                builder.Append(dateTime.ToString(\"yyyy'-'MM'-'dd'T'HH:mm:ss\", CultureInfo.InvariantCulture));\n                Duration.AppendNanoseconds(builder, nanoseconds);\n                builder.Append(\"Z\\\"\");\n                return builder.ToString();\n            }\n            if (diagnosticOnly)\n            {\n                return string.Format(CultureInfo.InvariantCulture,\n                    \"{{ \\\"@warning\\\": \\\"Invalid Timestamp\\\", \\\"seconds\\\": \\\"{0}\\\", \\\"nanos\\\": {1} }}\",\n                    seconds,\n                    nanoseconds);\n            }\n            else\n            {\n                throw new InvalidOperationException(\"Non-normalized timestamp value\");\n            }\n        }\n\n        /// <summary>\n        /// Returns a string representation of this <see cref=\"Timestamp\"/> for diagnostic purposes.\n        /// </summary>\n        /// <remarks>\n        /// Normally the returned value will be a JSON string value (including leading and trailing quotes) but\n        /// when the value is non-normalized or out of range, a JSON object representation will be returned\n        /// instead, including a warning. This is to avoid exceptions being thrown when trying to\n        /// diagnose problems - the regular JSON formatter will still throw an exception for non-normalized\n        /// values.\n        /// </remarks>\n        /// <returns>A string representation of this value.</returns>\n        public string ToDiagnosticString()\n        {\n            return ToJson(Seconds, Nanos, true);\n        }","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/XINCGer/Unity3DTraining/blob/016f98412ea5e11756b286736f479b66ab6216d5/NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/WellKnownTypes/TimestampPartial.cs#L205-L241","documentation":"Timestamp.ToJson (reached via ToDiagnosticString) serializes RFC 3339 timestamps, which requires normalized values: Nanos in [0, 999999999] and Seconds within the representable range (0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z). Out-of-range Seconds get a '@warning' JSON fallback, but non-normalized values (e.g. negative Nanos) throw InvalidOperationException.","triggerScenarios":"Calling ToDiagnosticString()/ToJson() on a Timestamp with Nanos < 0, Nanos >= 1_000_000_000, or Seconds outside the RFC 3339 representable window.","commonSituations":"Timestamps built by manual arithmetic on Seconds/Nanos without carrying; interop with producers emitting negative nanos; overflow when converting milliseconds/microseconds to nanos; corrupted or fuzzed wire data.","solutions":["Normalize before serializing: move nanos overflow into Seconds and ensure 0 <= Nanos < 1_000_000_000","Construct via Timestamp.FromDateTime(DateTime.UtcNow) or from the parser rather than setting fields directly","Validate Nanos/Seconds before calling ToJson and repair or reject invalid values","Log the raw Seconds/Nanos from the exception path to identify the faulty producer"],"exampleFix":"// before\nvar ts = new Timestamp { Seconds = 10, Nanos = -1 };\nvar s = ts.ToDiagnosticString(); // throws\n// after\nvar ts2 = new Timestamp { Seconds = 9, Nanos = 999_999_999 };\nvar s2 = ts2.ToDiagnosticString(); // \"2009-...\" normalized RFC3339","handlingStrategy":"validation","validationCode":"static bool IsNormalizedTimestamp(Timestamp t) => t.Nanos >= 0 && t.Nanos < 1_000_000_000 && t.Seconds >= -62135596800L && t.Seconds <= 253402300799L;","typeGuard":"static bool IsSerializableTimestamp(Timestamp t) => t != null && t.Nanos >= 0 && t.Nanos < 1_000_000_000;","tryCatchPattern":"try { return ts.ToDiagnosticString(); } catch (InvalidOperationException ex) { log.Warn(ex, \"Non-normalized timestamp {Seconds}/{Nanos}\", ts.Seconds, ts.Nanos); return $\"{ts.Seconds}.{ts.Nanos} (non-normalized)\"; }","preventionTips":["Normalize Nanos into Seconds after any arithmetic","Build timestamps via FromDateTime/FromDateTimeOffset, not raw fields","Sanitize wire input before storing/serializing Timestamps"],"tags":["protobuf","c-sharp","timestamp","serialization"],"backgroundTag":"value-out-of-range","analyzedSha":"016f98412ea5e11756b286736f479b66ab6216d5","analyzedAt":"2026-09-12T01:08:58.711Z","contentChangedAt":"2026-09-12T01:08:58.711Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}