{"record":{"id":"d0fda7284fbcb720","repo":"ppy/osu","slug":"bad-ticks-count-read","errorCode":null,"errorMessage":"Bad ticks count read!","messagePattern":"Bad ticks count read!","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"osu.Game/IO/Legacy/SerializationReader.cs","lineNumber":60,"sourceCode":"\r\n            return Array.Empty<byte>();\r\n        }\r\n\r\n        /// <summary> Reads a char array from the buffer, handling nulls and the array length. </summary>\r\n        public char[] ReadCharArray()\r\n        {\r\n            int len = ReadInt32();\r\n            if (len > 0) return ReadChars(len);\r\n            if (len < 0) return null;\r\n\r\n            return Array.Empty<char>();\r\n        }\r\n\r\n        /// <summary> Reads a DateTime from the buffer. </summary>\r\n        public DateTime ReadDateTime()\r\n        {\r\n            long ticks = ReadInt64();\r\n            if (ticks < 0) throw new IOException(\"Bad ticks count read!\");\r\n\r\n            return new DateTime(ticks, DateTimeKind.Utc);\r\n        }\r\n\r\n        /// <summary> Reads a generic list from the buffer. </summary>\r\n        public IList<T> ReadBList<T>(bool skipErrors = false) where T : ILegacySerializable, new()\r\n        {\r\n            int count = ReadInt32();\r\n            if (count < 0) return null;\r\n\r\n            IList<T> d = new List<T>(count);\r\n\r\n            SerializationReader sr = new SerializationReader(BaseStream);\r\n\r\n            for (int i = 0; i < count; i++)\r\n            {\r\n                T obj = new T();\r\n\r","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/IO/Legacy/SerializationReader.cs#L42-L78","documentation":"Thrown by SerializationReader.ReadDateTime after reading an Int64 ticks value; if ticks < 0 the stream contains an invalid DateTime (DateTime ticks must be non-negative). This is a defence against corrupt/truncated legacy replay/replay-frame data in the osu! serialisation format.","triggerScenarios":"Reading a DateTime field from a legacy serialised stream (.osr replay or related binary blob) where the 8-byte ticks value decodes to a negative number — caused by a truncated, swapped, or corrupt byte stream, or a version mismatch in the replay format.","commonSituations":"Parsing a damaged replay file, a replay from an incompatible game version, or a hand-crafted/edited binary. Also when the reader's position is wrong (misaligned reads earlier consuming the wrong bytes).","solutions":["Validate the replay file integrity/version before deserialising; reject files with an unknown/corrupt header.","Ensure prior reads consumed the correct number of bytes for the format version (a misaligned read makes the Int64 decode garbage).","Wrap deserialisation in try/catch(IOException) and treat the replay as unreadable, keeping the score record but dropping the replay."],"exampleFix":"// before\npublic DateTime ReadDateTime()\n{\n    long ticks = ReadInt64();\n    if (ticks < 0) throw new IOException(\"Bad ticks count read!\");\n    return new DateTime(ticks, DateTimeKind.Utc);\n}\n\n// after (caller-side graceful handling)\ntry\n{\n    DateTime ts = reader.ReadDateTime();\n}\ncatch (IOException)\n{\n    Logger.Log(\"Replay stream corrupt at DateTime field; replay discarded.\", LoggingTarget.Database, LogLevel.Important);\n    return;\n}","handlingStrategy":"try-catch","validationCode":"// Validate stream length/version header before reading fields.\nif (stream.Length < expectedMinLength) throw new InvalidDataException(\"Replay stream too short.\");","typeGuard":null,"tryCatchPattern":"try { var dt = reader.ReadDateTime(); }\ncatch (IOException) { /* discard corrupt replay, keep score metadata */ }","preventionTips":["Read legacy blobs only from sources matching the expected format version.","Keep reader calls in try/catch(IOException) so one corrupt field doesn't crash import.","Log the stream offset when corrupt data is hit to aid diagnosis."],"tags":["serialization","replay","binary-format","data-integrity","io"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}