FAILURE MAP
← Case archive

FA-77876 / Subtitle cue timing / Open access

SRT and WebVTT timestamp formatting: srt millisecond padding · case 01

An SRT cue at 1.050 s is written as 00:00:01,50, which readers interpret as 500 ms.

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

ROOT CAUSE

The SRT millisecond field is printed with %d and loses its leading zeros.

VERIFIED REPAIR

Zero-pad the SRT millisecond field to three digits.

Unsuccessful approach: Space-padding with %3d keeps the width but produces an illegal blank inside the timestamp.

Case contract

Format integer milliseconds as a cue timestamp. Negative values clamp to 0. style "srt" gives HH:MM:SS,mmm (hours at least two digits, never wrapped); style "vtt" gives MM:SS.mmm when the hour field is zero and HH:MM:SS.mmm otherwise.

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

N = 1
observations = []
def solve(ms, style):
    if ms<0: ms=0
    h=ms//3600000
    m=(ms-h*3600000)//60000
    s=ms//1000%60
    f=ms%1000
    if style=='srt':
        return '%02d:%02d:%02d,%d'%(h,m,s,f)
    if h==0:
        return '%02d:%02d.%03d'%(m,s,f)
    return '%02d:%02d:%02d.%03d'%(h,m,s,f)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: srt millisecond padding', [0, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [5, 'srt'], '00:00:00,005'), ('partial repair probe: srt millisecond padding', [3541034, 'srt'], '00:59:01,034'), ('partial repair variant: srt millisecond padding', [36000000, 'srt'], '10:00:00,000'), ('boundary control', [0, 'vtt'], '00:00.000'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('normal control', [3600000, 'vtt'], '01:00:00.000'), ('normal control', [7834, 'srt'], '00:00:07,834'), ('normal control', [3664439, 'srt'], '01:01:04,439')], [('regression: srt millisecond padding', [-1, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [360000000, 'srt'], '100:00:00,000'), ('partial repair probe: srt millisecond padding', [-5000, 'srt'], '00:00:00,000'), ('partial repair variant: srt millisecond padding', [30977039, 'srt'], '08:36:17,039'), ('boundary control', [3600000, 'vtt'], '01:00:00.000'), ('boundary control', [0, 'vtt'], '00:00.000'), ('normal control', [-999, 'vtt'], '00:00.000'), ('normal control', [893654, 'srt'], '00:14:53,654'), ('normal control', [55880, 'vtt'], '00:55.880')], [('regression: srt millisecond padding', [3541034, 'srt'], '00:59:01,034'), ('regression variant: srt millisecond padding', [-1000, 'srt'], '00:00:00,000'), ('partial repair probe: srt millisecond padding', [60000, 'srt'], '00:01:00,000'), ('partial repair variant: srt millisecond padding', [3327047, 'srt'], '00:55:27,047'), ('boundary control', [3599999, 'vtt'], '59:59.999'), ('boundary control', [3600000, 'vtt'], '01:00:00.000'), ('normal control', [11761, 'vtt'], '00:11.761'), ('normal control', [-5000, 'vtt'], '00:00.000'), ('normal control', [3576784, 'srt'], '00:59:36,784')], [('regression: srt millisecond padding', [-5000, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [-999, 'srt'], '00:00:00,000'), ('partial repair probe: srt millisecond padding', [5, 'srt'], '00:00:00,005'), ('partial repair variant: srt millisecond padding', [379730021, 'srt'], '105:28:50,021'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('boundary control', [3599999, 'vtt'], '59:59.999'), ('normal control', [59999, 'vtt'], '00:59.999'), ('normal control', [3509491, 'srt'], '00:58:29,491'), ('normal control', [175213793, 'vtt'], '48:40:13.793')], [('regression: srt millisecond padding', [60000, 'srt'], '00:01:00,000'), ('regression variant: srt millisecond padding', [36000000, 'srt'], '10:00:00,000'), ('partial repair probe: srt millisecond padding', [360000000, 'srt'], '100:00:00,000'), ('partial repair variant: srt millisecond padding', [3661001, 'srt'], '01:01:01,001'), ('boundary control', [0, 'vtt'], '00:00.000'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('normal control', [3689889, 'srt'], '01:01:29,889'), ('normal control', [3673366, 'srt'], '01:01:13,366'), ('normal control', [290743422, 'vtt'], '80:45:43.422')]]
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: srt millisecond padding00:00:00,000:00:00,000Failed
regression variant: srt millisecond padding00:00:00,500:00:00,005Failed
partial repair probe: srt millisecond padding00:59:01,3400:59:01,034Failed
partial repair variant: srt millisecond padding10:00:00,010:00:00,000Failed
boundary control00:00.00000:00.000Passed
boundary control01:01.00101:01.001Passed
normal control01:00:00.00001:00:00.000Passed
normal control00:00:07,83400:00:07,834Passed
normal control01:01:04,43901:01:04,439Passed

SHA-256 / 675fa572e4a2a06f0a377d1eb8eca89353bec6d668b9a2e471d825d22822944b

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(ms, style):
    if ms<0: ms=0
    h=ms//3600000
    m=(ms-h*3600000)//60000
    s=ms//1000%60
    f=ms%1000
    if style=='srt':
        return '%02d:%02d:%02d,%3d'%(h,m,s,f)
    if h==0:
        return '%02d:%02d.%03d'%(m,s,f)
    return '%02d:%02d:%02d.%03d'%(h,m,s,f)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: srt millisecond padding', [0, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [5, 'srt'], '00:00:00,005'), ('partial repair probe: srt millisecond padding', [3541034, 'srt'], '00:59:01,034'), ('partial repair variant: srt millisecond padding', [36000000, 'srt'], '10:00:00,000'), ('boundary control', [0, 'vtt'], '00:00.000'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('normal control', [3600000, 'vtt'], '01:00:00.000'), ('normal control', [7834, 'srt'], '00:00:07,834'), ('normal control', [3664439, 'srt'], '01:01:04,439')], [('regression: srt millisecond padding', [-1, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [360000000, 'srt'], '100:00:00,000'), ('partial repair probe: srt millisecond padding', [-5000, 'srt'], '00:00:00,000'), ('partial repair variant: srt millisecond padding', [30977039, 'srt'], '08:36:17,039'), ('boundary control', [3600000, 'vtt'], '01:00:00.000'), ('boundary control', [0, 'vtt'], '00:00.000'), ('normal control', [-999, 'vtt'], '00:00.000'), ('normal control', [893654, 'srt'], '00:14:53,654'), ('normal control', [55880, 'vtt'], '00:55.880')], [('regression: srt millisecond padding', [3541034, 'srt'], '00:59:01,034'), ('regression variant: srt millisecond padding', [-1000, 'srt'], '00:00:00,000'), ('partial repair probe: srt millisecond padding', [60000, 'srt'], '00:01:00,000'), ('partial repair variant: srt millisecond padding', [3327047, 'srt'], '00:55:27,047'), ('boundary control', [3599999, 'vtt'], '59:59.999'), ('boundary control', [3600000, 'vtt'], '01:00:00.000'), ('normal control', [11761, 'vtt'], '00:11.761'), ('normal control', [-5000, 'vtt'], '00:00.000'), ('normal control', [3576784, 'srt'], '00:59:36,784')], [('regression: srt millisecond padding', [-5000, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [-999, 'srt'], '00:00:00,000'), ('partial repair probe: srt millisecond padding', [5, 'srt'], '00:00:00,005'), ('partial repair variant: srt millisecond padding', [379730021, 'srt'], '105:28:50,021'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('boundary control', [3599999, 'vtt'], '59:59.999'), ('normal control', [59999, 'vtt'], '00:59.999'), ('normal control', [3509491, 'srt'], '00:58:29,491'), ('normal control', [175213793, 'vtt'], '48:40:13.793')], [('regression: srt millisecond padding', [60000, 'srt'], '00:01:00,000'), ('regression variant: srt millisecond padding', [36000000, 'srt'], '10:00:00,000'), ('partial repair probe: srt millisecond padding', [360000000, 'srt'], '100:00:00,000'), ('partial repair variant: srt millisecond padding', [3661001, 'srt'], '01:01:01,001'), ('boundary control', [0, 'vtt'], '00:00.000'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('normal control', [3689889, 'srt'], '01:01:29,889'), ('normal control', [3673366, 'srt'], '01:01:13,366'), ('normal control', [290743422, 'vtt'], '80:45:43.422')]]
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: srt millisecond padding00:00:00, 000:00:00,000Failed
regression variant: srt millisecond padding00:00:00, 500:00:00,005Failed
partial repair probe: srt millisecond padding00:59:01, 3400:59:01,034Failed
partial repair variant: srt millisecond padding10:00:00, 010:00:00,000Failed
boundary control00:00.00000:00.000Passed
boundary control01:01.00101:01.001Passed
normal control01:00:00.00001:00:00.000Passed
normal control00:00:07,83400:00:07,834Passed
normal control01:01:04,43901:01:04,439Passed

SHA-256 / a9347308fccf78bacbb2886d68ab6217b3a26f7c539e2202aa8c9f926626363f

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(ms, style):
    if ms<0: ms=0
    h=ms//3600000
    m=(ms-h*3600000)//60000
    s=ms//1000%60
    f=ms%1000
    if style=='srt':
        return '%02d:%02d:%02d,%03d'%(h,m,s,f)
    if h==0:
        return '%02d:%02d.%03d'%(m,s,f)
    return '%02d:%02d:%02d.%03d'%(h,m,s,f)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: srt millisecond padding', [0, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [5, 'srt'], '00:00:00,005'), ('partial repair probe: srt millisecond padding', [3541034, 'srt'], '00:59:01,034'), ('partial repair variant: srt millisecond padding', [36000000, 'srt'], '10:00:00,000'), ('boundary control', [0, 'vtt'], '00:00.000'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('normal control', [3600000, 'vtt'], '01:00:00.000'), ('normal control', [7834, 'srt'], '00:00:07,834'), ('normal control', [3664439, 'srt'], '01:01:04,439')], [('regression: srt millisecond padding', [-1, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [360000000, 'srt'], '100:00:00,000'), ('partial repair probe: srt millisecond padding', [-5000, 'srt'], '00:00:00,000'), ('partial repair variant: srt millisecond padding', [30977039, 'srt'], '08:36:17,039'), ('boundary control', [3600000, 'vtt'], '01:00:00.000'), ('boundary control', [0, 'vtt'], '00:00.000'), ('normal control', [-999, 'vtt'], '00:00.000'), ('normal control', [893654, 'srt'], '00:14:53,654'), ('normal control', [55880, 'vtt'], '00:55.880')], [('regression: srt millisecond padding', [3541034, 'srt'], '00:59:01,034'), ('regression variant: srt millisecond padding', [-1000, 'srt'], '00:00:00,000'), ('partial repair probe: srt millisecond padding', [60000, 'srt'], '00:01:00,000'), ('partial repair variant: srt millisecond padding', [3327047, 'srt'], '00:55:27,047'), ('boundary control', [3599999, 'vtt'], '59:59.999'), ('boundary control', [3600000, 'vtt'], '01:00:00.000'), ('normal control', [11761, 'vtt'], '00:11.761'), ('normal control', [-5000, 'vtt'], '00:00.000'), ('normal control', [3576784, 'srt'], '00:59:36,784')], [('regression: srt millisecond padding', [-5000, 'srt'], '00:00:00,000'), ('regression variant: srt millisecond padding', [-999, 'srt'], '00:00:00,000'), ('partial repair probe: srt millisecond padding', [5, 'srt'], '00:00:00,005'), ('partial repair variant: srt millisecond padding', [379730021, 'srt'], '105:28:50,021'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('boundary control', [3599999, 'vtt'], '59:59.999'), ('normal control', [59999, 'vtt'], '00:59.999'), ('normal control', [3509491, 'srt'], '00:58:29,491'), ('normal control', [175213793, 'vtt'], '48:40:13.793')], [('regression: srt millisecond padding', [60000, 'srt'], '00:01:00,000'), ('regression variant: srt millisecond padding', [36000000, 'srt'], '10:00:00,000'), ('partial repair probe: srt millisecond padding', [360000000, 'srt'], '100:00:00,000'), ('partial repair variant: srt millisecond padding', [3661001, 'srt'], '01:01:01,001'), ('boundary control', [0, 'vtt'], '00:00.000'), ('boundary control', [61001, 'vtt'], '01:01.001'), ('normal control', [3689889, 'srt'], '01:01:29,889'), ('normal control', [3673366, 'srt'], '01:01:13,366'), ('normal control', [290743422, 'vtt'], '80:45:43.422')]]
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: srt millisecond padding00:00:00,00000:00:00,000Passed
regression variant: srt millisecond padding00:00:00,00500:00:00,005Passed
partial repair probe: srt millisecond padding00:59:01,03400:59:01,034Passed
partial repair variant: srt millisecond padding10:00:00,00010:00:00,000Passed
boundary control00:00.00000:00.000Passed
boundary control01:01.00101:01.001Passed
normal control01:00:00.00001:00:00.000Passed
normal control00:00:07,83400:00:07,834Passed
normal control01:01:04,43901:01:04,439Passed

SHA-256 / 6e31c12810576c45803f6ef033e2a2a8526aa92b12dda39ccbe03034edfdb9f1

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:30.024729+00:00.

Case digest / 5c8db010e2e70b336c7bad09e97cc984fbb89d59b48fd5f288319a2e6ca670c3