FAILURE MAP
← Case archive

FA-78181 / Subtitle cue timing / Open access

WebVTT cue timing line parsing: cue ordering check · case 01

Zero-duration cues where END equals START are accepted.

Verified by executionVariant 1 · 9 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The order check only rejects ends strictly before the start.

VERIFIED REPAIR

Reject cues whose end is not after the start.

Unsuccessful approach: Special-casing an end of zero still accepts equal non-zero start and end.

Case contract

Parse "START --> END [settings...]" (whitespace separated). Timestamps are [hh:]mm:ss.ttt with hours of two or more digits, minutes and seconds exactly two digits below 60, and exactly three fraction digits after a period. END must be after START. Return [start_ms,end_ms,settings joined by single spaces] or None.

Why this case matters

Subtitle timing defects shift, hide or overlap captions that viewers depend on for comprehension and accessibility.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(line):
    parts=line.split()
    if len(parts)<3 or parts[1]!='-->':
        return None
    def ts(x):
        m=re.fullmatch(r'(?:(\d{2,}):)?(\d{2}):(\d{2})\.(\d{3})',x)
        if not m:
            return None
        h,mi,se,f=m.groups()
        if int(mi)>59 or int(se)>59:
            return None
        return int(h or 0)*3600000+int(mi)*60000+int(se)*1000+int(f)
    a=ts(parts[0]); b=ts(parts[2])
    if a is None or b is None or b<a:
        return None
    return [a,b,' '.join(parts[3:])]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: cue ordering check', ['00:01.000 --> 00:01.000'], None), ('regression variant: cue ordering check', ['01:00.500 --> 01:00.500'], None), ('partial repair probe: cue ordering check', ['01:09.500 --> 01:09.500'], None), ('partial repair variant: cue ordering check', ['100:59:59.999 --> 100:59:59.999 align:start'], None), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('normal control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['59:09.5 --> 00:02.000 align:start'], None), ('normal control', ['100:01:60,500 --> 00:00:60.5 align:start'], None)], [('regression: cue ordering check', ['100:59:09.000 --> 100:59:09.000'], None), ('regression variant: cue ordering check', ['100:59:09.500 --> 100:59:09.500 align:start'], None), ('partial repair probe: cue ordering check', ['00:00:09.000 --> 00:00:09.000'], None), ('partial repair variant: cue ordering check', ['00:59.000 --> 00:59.000 line:0 position:10%'], None), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['00:5:00.000 -> 00:5:00.000'], None), ('normal control', ['01:01:09.5 --> 60:09.5 size:50% align:end'], None), ('normal control', ['01:60:59.999 --> 00:00.001 line:0 position:10%'], None)], [('regression: cue ordering check', ['01:09.500 --> 01:09.500'], None), ('regression variant: cue ordering check', ['01:59:00.500 --> 01:59:00.500 size:50% align:end'], None), ('partial repair probe: cue ordering check', ['01:59:59.500 --> 01:59:59.500 size:50% align:end'], None), ('partial repair variant: cue ordering check', ['00:01:00.000 --> 00:01:00.000'], None), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('normal control', ['01:60:00.500 --> 5:60,500 line:0 position:10%'], None), ('normal control', ['100:01:00,500 --> 01:00:00.000 align:start'], None), ('normal control', ['60:59.500 --> 100:00:00.000'], None)], [('regression: cue ordering check', ['00:00:09.000 --> 00:00:09.000'], None), ('regression variant: cue ordering check', ['100:59:00.000 --> 100:59:00.000 size:50% align:end'], None), ('partial repair probe: cue ordering check', ['01:00.500 --> 01:00.500'], None), ('partial repair variant: cue ordering check', ['00:59:00.999 --> 00:59:00.999 size:50% align:end'], None), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('normal control', ['60:60.999 --> 00:00.001'], None), ('normal control', ['01:59:59,500 --> 01:59:59,500 size:50% align:end'], None), ('normal control', ['59:60.5 --> 100:00:00.000 line:0 position:10%'], None)], [('regression: cue ordering check', ['01:59:59.500 --> 01:59:59.500 size:50% align:end'], None), ('regression variant: cue ordering check', ['100:59:59.999 --> 100:59:59.999 align:start'], None), ('partial repair probe: cue ordering check', ['100:59:09.500 --> 100:59:09.500 align:start'], None), ('partial repair variant: cue ordering check', ['01:59:59.999 --> 01:59:59.999'], None), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['01:5:60.500 --> 00:00.001 size:50% align:end'], None), ('normal control', ['100:00:59.000 --> 00:02.000 size:50% align:end'], None), ('normal control', ['59:59.5 -> 00:5:59.999'], None)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: cue ordering check[1000, 1000, '']NoneFailed
regression variant: cue ordering check[60500, 60500, '']NoneFailed
partial repair probe: cue ordering check[69500, 69500, '']NoneFailed
partial repair variant: cue ordering check[363599999, 363599999, 'align:start']NoneFailed
boundary control[1000, 2000, ''][1000, 2000, '']Passed
boundary control[360000000, 360001000, 'align:start'][360000000, 360001000, 'align:start']Passed
normal control[59999, 60000, 'line:0 size:50%'][59999, 60000, 'line:0 size:50%']Passed
normal controlNoneNonePassed
normal controlNoneNonePassed

SHA-256 / d75a2bb861a088ac682e5b1bf9f82df1199ae189c73d88e28d4eb5d660453122

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(line):
    parts=line.split()
    if len(parts)<3 or parts[1]!='-->':
        return None
    def ts(x):
        m=re.fullmatch(r'(?:(\d{2,}):)?(\d{2}):(\d{2})\.(\d{3})',x)
        if not m:
            return None
        h,mi,se,f=m.groups()
        if int(mi)>59 or int(se)>59:
            return None
        return int(h or 0)*3600000+int(mi)*60000+int(se)*1000+int(f)
    a=ts(parts[0]); b=ts(parts[2])
    if a is None or b is None or b<a or b==0:
        return None
    return [a,b,' '.join(parts[3:])]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: cue ordering check', ['00:01.000 --> 00:01.000'], None), ('regression variant: cue ordering check', ['01:00.500 --> 01:00.500'], None), ('partial repair probe: cue ordering check', ['01:09.500 --> 01:09.500'], None), ('partial repair variant: cue ordering check', ['100:59:59.999 --> 100:59:59.999 align:start'], None), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('normal control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['59:09.5 --> 00:02.000 align:start'], None), ('normal control', ['100:01:60,500 --> 00:00:60.5 align:start'], None)], [('regression: cue ordering check', ['100:59:09.000 --> 100:59:09.000'], None), ('regression variant: cue ordering check', ['100:59:09.500 --> 100:59:09.500 align:start'], None), ('partial repair probe: cue ordering check', ['00:00:09.000 --> 00:00:09.000'], None), ('partial repair variant: cue ordering check', ['00:59.000 --> 00:59.000 line:0 position:10%'], None), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['00:5:00.000 -> 00:5:00.000'], None), ('normal control', ['01:01:09.5 --> 60:09.5 size:50% align:end'], None), ('normal control', ['01:60:59.999 --> 00:00.001 line:0 position:10%'], None)], [('regression: cue ordering check', ['01:09.500 --> 01:09.500'], None), ('regression variant: cue ordering check', ['01:59:00.500 --> 01:59:00.500 size:50% align:end'], None), ('partial repair probe: cue ordering check', ['01:59:59.500 --> 01:59:59.500 size:50% align:end'], None), ('partial repair variant: cue ordering check', ['00:01:00.000 --> 00:01:00.000'], None), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('normal control', ['01:60:00.500 --> 5:60,500 line:0 position:10%'], None), ('normal control', ['100:01:00,500 --> 01:00:00.000 align:start'], None), ('normal control', ['60:59.500 --> 100:00:00.000'], None)], [('regression: cue ordering check', ['00:00:09.000 --> 00:00:09.000'], None), ('regression variant: cue ordering check', ['100:59:00.000 --> 100:59:00.000 size:50% align:end'], None), ('partial repair probe: cue ordering check', ['01:00.500 --> 01:00.500'], None), ('partial repair variant: cue ordering check', ['00:59:00.999 --> 00:59:00.999 size:50% align:end'], None), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('normal control', ['60:60.999 --> 00:00.001'], None), ('normal control', ['01:59:59,500 --> 01:59:59,500 size:50% align:end'], None), ('normal control', ['59:60.5 --> 100:00:00.000 line:0 position:10%'], None)], [('regression: cue ordering check', ['01:59:59.500 --> 01:59:59.500 size:50% align:end'], None), ('regression variant: cue ordering check', ['100:59:59.999 --> 100:59:59.999 align:start'], None), ('partial repair probe: cue ordering check', ['100:59:09.500 --> 100:59:09.500 align:start'], None), ('partial repair variant: cue ordering check', ['01:59:59.999 --> 01:59:59.999'], None), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['01:5:60.500 --> 00:00.001 size:50% align:end'], None), ('normal control', ['100:00:59.000 --> 00:02.000 size:50% align:end'], None), ('normal control', ['59:59.5 -> 00:5:59.999'], None)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: cue ordering check[1000, 1000, '']NoneFailed
regression variant: cue ordering check[60500, 60500, '']NoneFailed
partial repair probe: cue ordering check[69500, 69500, '']NoneFailed
partial repair variant: cue ordering check[363599999, 363599999, 'align:start']NoneFailed
boundary control[1000, 2000, ''][1000, 2000, '']Passed
boundary control[360000000, 360001000, 'align:start'][360000000, 360001000, 'align:start']Passed
normal control[59999, 60000, 'line:0 size:50%'][59999, 60000, 'line:0 size:50%']Passed
normal controlNoneNonePassed
normal controlNoneNonePassed

SHA-256 / a4ec6581f9e35b30941c982abcbb8ad49208dafbb875b99c2b2ef7e0f61b8716

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import re
N = 1
observations = []
def solve(line):
    parts=line.split()
    if len(parts)<3 or parts[1]!='-->':
        return None
    def ts(x):
        m=re.fullmatch(r'(?:(\d{2,}):)?(\d{2}):(\d{2})\.(\d{3})',x)
        if not m:
            return None
        h,mi,se,f=m.groups()
        if int(mi)>59 or int(se)>59:
            return None
        return int(h or 0)*3600000+int(mi)*60000+int(se)*1000+int(f)
    a=ts(parts[0]); b=ts(parts[2])
    if a is None or b is None or b<=a:
        return None
    return [a,b,' '.join(parts[3:])]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: cue ordering check', ['00:01.000 --> 00:01.000'], None), ('regression variant: cue ordering check', ['01:00.500 --> 01:00.500'], None), ('partial repair probe: cue ordering check', ['01:09.500 --> 01:09.500'], None), ('partial repair variant: cue ordering check', ['100:59:59.999 --> 100:59:59.999 align:start'], None), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('normal control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['59:09.5 --> 00:02.000 align:start'], None), ('normal control', ['100:01:60,500 --> 00:00:60.5 align:start'], None)], [('regression: cue ordering check', ['100:59:09.000 --> 100:59:09.000'], None), ('regression variant: cue ordering check', ['100:59:09.500 --> 100:59:09.500 align:start'], None), ('partial repair probe: cue ordering check', ['00:00:09.000 --> 00:00:09.000'], None), ('partial repair variant: cue ordering check', ['00:59.000 --> 00:59.000 line:0 position:10%'], None), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['00:5:00.000 -> 00:5:00.000'], None), ('normal control', ['01:01:09.5 --> 60:09.5 size:50% align:end'], None), ('normal control', ['01:60:59.999 --> 00:00.001 line:0 position:10%'], None)], [('regression: cue ordering check', ['01:09.500 --> 01:09.500'], None), ('regression variant: cue ordering check', ['01:59:00.500 --> 01:59:00.500 size:50% align:end'], None), ('partial repair probe: cue ordering check', ['01:59:59.500 --> 01:59:59.500 size:50% align:end'], None), ('partial repair variant: cue ordering check', ['00:01:00.000 --> 00:01:00.000'], None), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('normal control', ['01:60:00.500 --> 5:60,500 line:0 position:10%'], None), ('normal control', ['100:01:00,500 --> 01:00:00.000 align:start'], None), ('normal control', ['60:59.500 --> 100:00:00.000'], None)], [('regression: cue ordering check', ['00:00:09.000 --> 00:00:09.000'], None), ('regression variant: cue ordering check', ['100:59:00.000 --> 100:59:00.000 size:50% align:end'], None), ('partial repair probe: cue ordering check', ['01:00.500 --> 01:00.500'], None), ('partial repair variant: cue ordering check', ['00:59:00.999 --> 00:59:00.999 size:50% align:end'], None), ('boundary control', ['00:01.000 --> 00:02.000'], [1000, 2000, '']), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('normal control', ['60:60.999 --> 00:00.001'], None), ('normal control', ['01:59:59,500 --> 01:59:59,500 size:50% align:end'], None), ('normal control', ['59:60.5 --> 100:00:00.000 line:0 position:10%'], None)], [('regression: cue ordering check', ['01:59:59.500 --> 01:59:59.500 size:50% align:end'], None), ('regression variant: cue ordering check', ['100:59:59.999 --> 100:59:59.999 align:start'], None), ('partial repair probe: cue ordering check', ['100:59:09.500 --> 100:59:09.500 align:start'], None), ('partial repair variant: cue ordering check', ['01:59:59.999 --> 01:59:59.999'], None), ('boundary control', ['100:00:00.000 --> 100:00:01.000 align:start'], [360000000, 360001000, 'align:start']), ('boundary control', ['00:59.999 --> 01:00.000 line:0 size:50%'], [59999, 60000, 'line:0 size:50%']), ('normal control', ['01:5:60.500 --> 00:00.001 size:50% align:end'], None), ('normal control', ['100:00:59.000 --> 00:02.000 size:50% align:end'], None), ('normal control', ['59:59.5 -> 00:5:59.999'], None)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: cue ordering checkNoneNonePassed
regression variant: cue ordering checkNoneNonePassed
partial repair probe: cue ordering checkNoneNonePassed
partial repair variant: cue ordering checkNoneNonePassed
boundary control[1000, 2000, ''][1000, 2000, '']Passed
boundary control[360000000, 360001000, 'align:start'][360000000, 360001000, 'align:start']Passed
normal control[59999, 60000, 'line:0 size:50%'][59999, 60000, 'line:0 size:50%']Passed
normal controlNoneNonePassed
normal controlNoneNonePassed

SHA-256 / 38cf253039aaff0cc9f8066ad812dc02d5d2477d16a8568e1e8c71cf319758f1

Verification & scope

A deterministic bounded teaching model with a stipulated toy contract; it does not claim conformance to any subtitle standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:49:32.746351+00:00.

Case digest / 6954345eb7421ce66492a8ae6eb535d1a7bb2f63d9539f816ae622196a325777