{"record":{"id":"75acfdca2fbef2f0","repo":"SubtitleEdit/subtitleedit","slug":"invalid-assa-time-code-time","errorCode":null,"errorMessage":"Invalid ASSA time code: {time}","messagePattern":"Invalid ASSA time code: (.+?)","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"error","filePath":"src/libse/SubtitleFormats/AdvancedSubStationAlpha.cs","lineNumber":1980,"sourceCode":"\n            subtitle.Renumber();\n            Errors = errors.ToString();\n        }\n\n        private static TimeCode GetTimeCodeFromString(string time)\n        {\n            // h:mm:ss.cc - parsed with span slices; this runs twice per Dialogue line when\n            // loading a file, and the previous Split(':', '.') allocated a string[] plus one\n            // substring per part for every call.\n            var span = time.AsSpan();\n            var i1 = span.IndexOfAny(':', '.');\n            var afterHours = i1 < 0 ? default : span.Slice(i1 + 1);\n            var i2 = afterHours.IndexOfAny(':', '.');\n            var afterMinutes = i2 < 0 ? default : afterHours.Slice(i2 + 1);\n            var i3 = afterMinutes.IndexOfAny(':', '.');\n            if (i1 < 0 || i2 < 0 || i3 < 0)\n            {\n                throw new FormatException($\"Invalid ASSA time code: {time}\");\n            }\n\n            var afterSeconds = afterMinutes.Slice(i3 + 1);\n            var i4 = afterSeconds.IndexOfAny(':', '.');\n            var lastPart = (i4 < 0 ? afterSeconds : afterSeconds.Slice(0, i4)).Trim();\n\n            var ms = 0;\n            if (lastPart.Length == 2) // correct ASSA time code\n            {\n                ms = int.Parse(lastPart) * 10;\n            }\n            else if (lastPart.Length == 3)\n            {\n                ms = int.Parse(lastPart); // 3 digits, e.g. 123 = 123 ms\n            }\n            else if (lastPart.Length > 3)\n            {\n                ms = int.Parse(lastPart.Slice(0, 2)) * 10;","sourceCodeStart":1962,"sourceCodeEnd":1998,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/libse/SubtitleFormats/AdvancedSubStationAlpha.cs#L1962-L1998","documentation":"Thrown by AdvancedSubStationAlpha.GetTimeCodeFromString when a Dialogue line's start/end time field does not contain the expected h:mm:ss.cc separators. The parser uses IndexOfAny(':', '.') three times to slice the span; if any of the three separators is missing (i1/i2/i3 < 0) the time is unparseable and a FormatException is raised. This fires twice per Dialogue line during file load.","triggerScenarios":"Loading an .ass/.ssa file whose Dialogue timing fields are malformed — e.g. '1:23' (missing seconds or centiseconds), '123' (no separators at all), empty string, or a value using a comma instead of a dot/colon. Also triggered if a non-ASSA file is misdetected as ASSA.","commonSituations":"Hand-edited subtitle files with typos in time fields, files generated by a buggy exporter that drops the centisecond part, locale-specific files using comma decimal separators, or files with trailing/leading whitespace in the time field.","solutions":["Open the .ass file in a text editor and verify every Dialogue line's start/end times match h:mm:ss.cc (e.g. 0:00:01.23).","If the file is a different format, force the correct format in SubtitleEdit instead of relying on auto-detection.","Fix the offending line(s) manually or re-export from the original source.","If loading programmatically, pre-validate times with a regex before calling LoadSubtitle."],"exampleFix":"// before\nDialogue: 0,1:23,2:00,Default,,0,0,0,,Hi\n// after\nDialogue: 0,0:01:23.00,0:02:00.00,Default,,0,0,0,,Hi","handlingStrategy":"validation","validationCode":"// Validate an ASSA time string before passing it to a loader/serializer\nstatic bool IsValidAssaTime(string time)\n{\n    if (string.IsNullOrWhiteSpace(time)) return false;\n    // Expect h:mm:ss.cc — at least three ':' or '.' separators\n    var sepCount = 0;\n    foreach (var c in time)\n    {\n        if (c == ':' || c == '.') sepCount++;\n    }\n    return sepCount >= 3;\n}\n\n// usage before load\nif (lines.Any(l => l.StartsWith(\"Dialogue:\", StringComparison.Ordinal)\n    && !IsValidAssaTime(l.Split(',')[1])))\n{\n    // warn user / sanitize\n}","typeGuard":null,"tryCatchPattern":"// Wrap LoadSubtitle to report the offending line\ntry\n{\n    new AdvancedSubStationAlpha().LoadSubtitle(sub, lines, fileName);\n}\ncatch (FormatException ex) when (ex.Message.StartsWith(\"Invalid ASSA time code\"))\n{\n    // log ex.Message, prompt user to fix the time field, do not swallow silently\n    logger.Error(ex, \"ASSA time code parse failed\");\n    throw;\n}","preventionTips":["Pre-validate Dialogue time fields with a regex like ^\\d+:\\d\\d:\\d\\d\\.\\d\\d$ before loading.","Avoid hand-editing time fields; use a subtitle editor that validates on save.","Sanitize imported files through a normalization pass that enforces h:mm:ss.cc."],"tags":["subtitle-format","assa","time-code","parsing","format-exception"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}