SCTE-35 ad-marker loss
across the live→VOD stitch seam.
A working postmortem on the Friday primetime VOD-publish event where the live-to-VOD stitcher dropped the splice_insert / splice_null cue points crossing the cdn-A → cdn-E seam, so the resulting VOD HLS manifest carried no EXT-X-CUE-OUT or EXT-X-DATERANGE cues and the downstream SSAI/DSA ad server never received the cue trigger — and the Streamwake agentic ops layer caught it from manifest + cue-coverage telemetry, ranked it as a stitcher cue filter overshoot with 89% confidence, and remediated it with a split live/VOD cue-pass policy plus a raised vod.cue_point_coverage probe — split explicitly into the acts the agent did autonomously and the acts it surfaced to humans.
Book a technical demo for SCTE-35 ad-marker loss (live→VOD stitching)
Read the postmortem — then bring your own incident to Streamwake.
Two ways to engage on this exact failure pattern: book a 30-minute technical demo where we walk through the probe cascade on your source, or hand us an archived incident and watch the agent diagnose it end-to-end.
Both routes land on the scoping intake form — no SDR gate.
What the cohort saw
The first things to read on any real primetime ad-insertion incident are the cohort-level numbers — how broad the cue-coverage collapse was, how many VOD assets carried cue-free manifests after the seam, and where the symptom landed on the stitcher cue filter. Three numbers did the heavy lifting here.
Roughly 22% of the eu-west primetime VOD-replay cohort — assets crossing thecdn-A → cdn-E stitch seam — left the packager with zero EXT-X-CUE-OUT / EXT-X-DATERANGE cues; downstream SSAI/DSA servers received no cue trigger on those assets, so pre-roll / mid-roll ad break count collapsed to ~1 per hour instead of the expected ~4 per hour.
~13 minutes between the first cue-drop on the cdn-A→cdn-E seam at T+0m and the vod.cue_point_coverage probe returning to 1.0 at T+41m. The postmortem window goes longer because the split cue-pass policy ships as a deploy-time config — not in the same incident window.
scte35.cue_dropped: true on seam_header (cdn-A → cdn-E) with vod.cue_point_coverage: 0.0 on the first VOD segment after the seam. The cue points were healthy upstream on live egress; the failure was on the stitcher’s shared cue filter leaking into the VOD path, not on the source signal.
How Streamwake classified this incident
Three ranked hypotheses, with the top one filing the timeline and the secondary signal carrying the cause. The vod_manifest_missing_cue and scte35_signal_replay_normal lanes are included to make explicit that the agent ruled them out — the symptom was on the stitcher cue filter leaking into the VOD path, not on the manifest parser or the upstream SCTE-35 signal.
stitcher_cue_filter_overshoot — the stitcher’s shared cue filter (designed for the live egress anti cue-re-fire policy) leaked into the VOD stitch path and dropped every splice_insert / splice_null cue point crossing the cdn-A → cdn-E seam. Four signals line up: scte35.cue_dropped true on the seam header, vod.cue_point_coverage at 0.0 on the first VOD segment, vod.manifest_first_segment.ext_x_cue_out_count at 0 vs 4 expected, wrapper.scte35_signal_in_manifest fail (no EXT-X-CUE-OUT / EXT-X-DATERANGE post-seam).
vod_manifest_missing_cue was the secondary signal ranked at 7% — the VOD manifest parsed successfully on cdn-E (no parse errors), so the missing cues are a cue-passthrough gap on the stitcher, not a manifest construction failure on the packager. The dismissal rule ranked on the cue-coverage pattern rather than on manifest state alone, because the seam_header flag (file-level filter applied, no parse error on the VOD side) is the decisive signal for a passthrough regression.
- Region: eu-west (cdn-A → cdn-E)
- Status: resolved (window closed)
- Opened: 2026-08-07 19:38 UTC
- Spread: contained to eu-west stitch seam — na-east VOD cohort unaffected
Above the 80% threshold the agent treats as a confident top-hypothesis filing. scte35_signal_replay_normal · 0.04 was cleared explicitly because the live egress emitted 8 cue points across the 90s window with no signal error — the upstream splice_insert / splice_null signal was healthy; the failure was on the crossover into the VOD packager, not on the upstream signal.
Incident timeline
Ten events: detection on the cohort, classification across three ranked hypotheses, five autonomous acts the agent took on its own, three acts it surfaced to humans, and the resolution. The right-hand “act” tag is what makes this postmortem distinct from a generic write-up — it pins the split between autonomous agentic ops and the work that genuinely needed a person.
Today
- T+0mDetectionby cohort agent · eu-westact · autonomous
Stitcher dropped cue points crossing the cdn-A→cdn-E seam; VOD manifest cue-free after the seam
seam_header.scte35.cue_dropped flipped to true on the live→VOD stitch seam; vod.cue_point_coverage dropped to 0.0 on the first VOD segment after the seam; vod.manifest_first_segment.ext_x_cue_out_count fell to 0 vs the expected 4 per hour; ad_break_count_per_hour on the replayed asset collapsed from ~4 to ~1.
Aug 7, 07:38:04 PM - T+1mClassificationby Streamwake reliability agentact · autonomous
Ranked: stitcher_cue_filter_overshoot (0.89) · secondary vod_manifest_missing_cue (0.07)
Top hypothesis reads 89% confidence. Two ranked alternatives dismissed: vod_manifest_missing_cue (the manifest parses green on cdn-E — the gap is on the cue passthrough, not on manifest construction), scte35_signal_replay_normal (the live egress emitted 8 cue points across the 90s window — the upstream signal was healthy; the failure is specifically on the crossover into the VOD packager).
Aug 7, 07:39:04 PM - T+2mAutomated actionby Streamwake reliability agentact · autonomous
Emitted split_cue_pass_policy_live_vs_vod + raise_vod_cue_passer_threshold
Split the stitcher’s cue-pass policy so the live egress keeps the anti cue-re-fire filter (still required there) and the VOD path passes every cue point through unchanged. Raise the vod.cue_point_coverage threshold from 0.85 to 0.95 so the next cue passthrough regression surfaces as a hard miss instead of a quiet drift.
Aug 7, 07:40:04 PM - T+3mAutomated actionby Streamwake reliability agentact · autonomous
Pinned the stitcher to the pre-migration cue policy for affected VOD assets
Pinned the affected VOD asset cohort to the pre-migration shared cue policy (the filter that was active before the cdn-A→cdn-E migration) so the next publish keeps the cues intact while the vendor-side fix is reviewed; the post-migration policy stays in place for live egress.
Aug 7, 07:41:04 PM - T+6mAutomated actionby Streamwake reliability agentact · autonomous
Re-published 4 affected VOD assets with the split cue-pass policy in effect
Forced a replay-cycle publish on the 4 affected VOD assets that crossed the cdn-A→cdn-E seam during the incident window; the replayed assets now carry EXT-X-CUE-OUT / EXT-X-DATERANGE cues end-to-end and ad_break_count_per_hour is back at ~4 per hour.
Aug 7, 07:44:04 PM - T+9mAutomated actionby Streamwake reliability agentact · autonomous
Rebalance hint queued: dry-run the cue passthrough split off-peak over the weekend
Run a dry-run of the split_cue_pass_policy_live_vs_vod config on a low-volume replay cohort over the weekend (off-peak eu-west) before promoting it to the live VOD stitch path, so the post-migration cue policy can land on live egress without breaking cues on the VOD seam again. Staged for the next deploy.
Aug 7, 07:47:04 PM - T+16mSurfaced to humanby agent → operatoract · surfaced to humans
Operator engaged the stitcher vendor on the shared cue filter leaking into the VOD path
Vendor confirmed the shared cue filter config was retained unchanged from the pre-migration cue policy and was never split between the live egress and VOD stitch paths; the filter was correctly retaining the anti cue-re-fire behaviour on live egress, but its scope leaked into VOD, dropping every cue point crossing the seam. New policy: keep the live_egress_anti_refire_policy on live egress, switch VOD stitch to vod_passthrough_policy that passes every cue through unchanged.
Aug 7, 07:54:04 PM - T+19mSurfaced to humanby on-callact · surfaced to humans
On-call paged for the cue-drop root-cause review on the live→VOD seam
Page acknowledged within 70s; reviewer confirmed the agent’s rank and that the re-publish on the 4 affected VOD assets + the pinned pre-migration cue policy had restored ad_break_count_per_hour to its baseline before the formal fix ship.
Aug 7, 07:57:04 PM - T+24mSurfaced to humanby reliability teamact · surfaced to humans
Postmortem write-up assigned (this page)
Reliability team assigned the public postmortem; this page is the resulting write-up, with the ranked hypotheses, recommended fix, and agentic-act split pinned from the timeline.
Aug 7, 08:02:04 PM - T+41mResolutionby Operator + agentact · autonomous
Incident resolved; split cue-pass policy ships next deploy · vod.cue_point_coverage probe raised
vod.cue_point_coverage returned to 1.0 on the first VOD segment after the seam; vod.manifest_first_segment.ext_x_cue_out_count climbed back to 4 per hour on the affected assets; the split_cue_pass_policy_live_vs_vod config and the raised vod.cue_point_coverage probe threshold both ship in the next deploy window.
Aug 7, 08:19:04 PM
- classify · ranked three hypotheses with confidence in 90s
- split · emitted split_cue_pass_policy_live_vs_vod so the VOD path passes every cue point through
- threshold · emitted raise_vod_cue_passer_threshold so the next cue passthrough miss surfaces as a hard hit
- pin · pinned the affected VOD asset cohort to the pre-migration cue policy while the vendor-side fix ships
- republish · forced a re-publish on the 4 affected VOD assets with the split cue-pass policy in effect
- rebalance · queued a dry-run of the cue passthrough split off-peak over the weekend
- operator · engaged the stitcher vendor on the shared cue filter leaking into the VOD path
- on-call · paged for the cue-drop root-cause review on the live→VOD seam
- reliability team · assigned the public postmortem write-up (this page)
Anatomy of the evidence packet
The two packets on the failing source — a 12-line splice_insert cue excerpt crossing the cdn-A → cdn-E stitch seam (with the cue filter leaking across the seam and the resulting VOD HLS manifest cue-free after the seam) and the agent timeline response with the ranked hypotheses and the rebalance hints. The cue excerpt is what the agent decided on; the timeline response is what the agent emitted.
----- splice_insert cue excerpt (12 lines, crossing the cdn-A→cdn-E seam) -----
# section 1: live egress (cdn-A), 8 cue points emitted across the 90s window
[cue 1] splice_insert pts=441,243,200 dur=15000 preroll=4000 avp_segmentation_type=1
[cue 2] splice_null pts=442,118,400 dur=8000 avp_segmentation_type=1
[cue 3] splice_insert pts=443,920,100 dur=15000 preroll=4000 avp_segmentation_type=1
[cue 4] splice_null pts=445,082,600 dur=8000 avp_segmentation_type=1
[cue 5] splice_insert pts=446,704,400 dur=15000 preroll=4000 avp_segmentation_type=1
[cue 6] splice_null pts=447,884,200 dur=8000 avp_segmentation_type=1
[cue 7] splice_insert pts=449,406,700 dur=15000 preroll=4000 avp_segmentation_type=1
[cue 8] splice_null pts=450,719,500 dur=8000 avp_segmentation_type=1
# ─── stitch seam (cdn-A → cdn-E) ───────────────────────────────────────
# seam_header.scte35.cue_dropped: true
# seam_header.cue_filter_applied: live_egress_anti_refire_policy
# (the stitcher’s shared cue filter held across the seam; 8 cues dropped)
[cue 9] splice_insert pts=452,400,300 dur=15000 preroll=4000 avp_segmentation_type=1 # DROPPED
[cue 10] splice_null pts=453,930,000 dur=8000 avp_segmentation_type=1 # DROPPED
----- VOD HLS manifest excerpt (first 8 segments across the seam, after stitch) -----
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:42
#EXT-X-MAP:URI="init.mp4"
#EXTINF:6.000,
seg-042.m4s
#EXTINF:6.000,
seg-043.m4s
#EXTINF:6.000,
seg-044.m4s
#EXTINF:6.000,
seg-045.m4s
#EXTINF:6.000,
seg-046.m4s
#EXTINF:6.000,
seg-047.m4s
#EXTINF:6.000,
seg-048.m4s
#EXTINF:6.000,
seg-049.m4s
# ranking note: the VOD manifest carries zero `#EXT-X-CUE-OUT` and zero
# `#EXT-X-DATERANGE` lines after the seam — the splice_insert cues never
# reached the VOD packager. SSAI/DSA receives no cue trigger on this asset.
----- cycle 1 (T+0m +8s, after split live/VOD cue-pass policy) -----
seam_header.scte35.cue_dropped: false
seam_header.cue_filter_applied: vod_passthrough_policy
vod.cue_point_coverage: 1.0
vod.manifest_first_segment.ext_x_cue_out_count: 4
vod.manifest_first_segment.ext_x_daterange_count: 4
# rebalance_hints emitted: split_cue_pass_policy_live_vs_vod,
# raise_vod_cue_passer_threshold,
# pin_stitcher_to_pre_migration_cue_policy
# ad_break_count_per_hour (replayed asset): 4 (baseline was ~1)- scte35.cue_dropped →
true on seam_header (8 cues dropped) - vod.cue_point_coverage →
0.0 (fail, baseline 1.0) - vod.manifest_first_segment.ext_x_cue_out_count →
0 vs 4 expected per hour - wrapper.scte35_signal_in_manifest →
fail (no EXT-X-CUE-OUT / DATERANGE post-seam) - manifest parse → pass. VOD manifest parses green on cdn-E — symptom is on the stitcher filter, not the packager.
{
"stream_id": "cklivestitchertocuevod7921",
"source": "https://cdn.example.com/live/event/manifest.m3u8",
"protocol": "HLS+STITCH+SCTE-35",
"checked_at": "2026-08-07T19:46:02Z",
"ranked_hypotheses": [
{
"rank": 1,
"hypothesis": "stitcher_cue_filter_overshoot",
"confidence": 0.89,
"evidence_signals": [
"scte35.cue_dropped → fail (true on seam_header across cdn-A→cdn-E)",
"vod.cue_point_coverage → fail (0.0 on the first VOD segment after the seam)",
"vod.manifest_first_segment.ext_x_cue_out_count → fail (0 vs 4 expected per hour)",
"wrapper.scte35_signal_in_manifest → fail (no EXT-X-CUE-OUT / EXT-X-DATERANGE post-seam)"
]
},
{
"rank": 2,
"hypothesis": "vod_manifest_missing_cue",
"confidence": 0.07,
"evidence_signals": [
"manifest served green on cdn-E with no parse errors; the missing cues are a packager-side passthrough gap, not a manifest parse failure"
]
},
{
"rank": 3,
"hypothesis": "scte35_signal_replay_normal",
"confidence": 0.04,
"evidence_signals": [
"SCTE-35 signal healthy on the live egress (8 cue points across the 90s window); the failure is on the crossover into the VOD packager, not on the upstream signal"
]
}
],
"agent_rebalance_hints": [
"split_cue_pass_policy_live_vs_vod",
"raise_vod_cue_passer_threshold",
"pin_stitcher_to_pre_migration_cue_policy"
],
"surfaced_to_humans": [
{"owner": "stitcher vendor", "task": "engage on the shared cue filter leaking into the VOD path"},
{"owner": "on-call", "task": "page for the cue-drop root-cause review on the live→VOD seam"},
{"owner": "reliability team", "task": "assign the postmortem write-up"}
]
}- rebalance hint →
split_cue_pass_policy_live_vs_vod - rebalance hint →
raise_vod_cue_passer_threshold - rebalance hint →
pin_stitcher_to_pre_migration_cue_policy - rebalance hint →
dry_run_cue_passthrough_split_offpeak(queued, ships in the next deploy) - surfaced → engaged the stitcher vendor on the shared cue filter leaking into the VOD path
- surfaced → paged on-call for the cue-drop root-cause review on the live→VOD seam
Split the cue-pass policy live vs VOD · raise the vod.cue_point_coverage probe
Two changes close the gap the timeline exposed. The first is what the agent already emitted on this incident (the split live/VOD cue-pass policy + the re-publish on the 4 affected VOD assets); the second is what ships on the next deploy (the raised vod.cue_point_coverage probe threshold + the vendor-side shared cue filter audit). Both are tracked as exported rebalance_hints rows.
The stitcher’s shared cue filter (designed for the live egress anti cue-re-fire policy) was leaking into the VOD stitch path. The fix is to split the cue-pass policy by egress lane: keep live_egress_anti_refire_policy on the live egress path (still required there to prevent premature cue re-fire), and switch the VOD stitch path to vod_passthrough_policy that passes every splice_insert / splice_null cue point through unchanged. The agent emitted split_cue_pass_policy_live_vs_vod on the failing path and re-published the 4 affected VOD assets to restore ad_break_count_per_hour to its baseline before the formal fix shipped.
scte35.cue_dropped stays false on every seam_header for ten consecutive days; vod.cue_point_coverage stays at 1.0 on the first VOD segment after every seam, with vod.manifest_first_segment.ext_x_cue_out_count at the expected count per hour.
The vod.cue_point_coverage probe was set with a 0.85 threshold, which meant a cue passthrough regression that dragged coverage to 0.0 only landed as a quiet drift instead of a hard miss. Raising the threshold to 0.95 keeps the coverage lane trustworthy as a hard clip on the VOD stitch path and ensures the next cue passthrough regression surfaces as a real alert, not a quiet drift. The cohort impact at the current setting is a 0.0 cue coverage clipped by the 0.85 threshold; at the new setting it becomes a real cue-coverage alert, plus the seam_header flag it always fired. Ships next deploy alongside a dry-run of the cue passthrough split off-peak over the weekend.
vod.cue_point_coverage drift over the affected geo stays at 1.0 over a 24-hour window; vod.manifest_first_segment.ext_x_cue_out_count stays at the expected count per hour for ten consecutive seam crossings.
Want Streamwake to catch this on your live→VOD stitch path?
Sign up, register an HLS+STITCH+SCTE-35 probe, and the same scte35.cue_dropped · vod.cue_point_coverage · vod.manifest_first_segment.ext_x_cue_out_count · wrapper.scte35_signal_in_manifest probes that produced the timeline above run on every stitch seam — and surface in a Slack channel, a webhook, or the streams dashboard.
- Pick a recent on-call incident — manifest stall, edge miss, player-side stall, or peer congestion.
- We replay it through the same reliability-agent probe cascade used on the postmortem above.
- You walk away with a written what-could-have-been-Automated readout, not a sales deck.
Read the next postmortem
The other live entries cover DRM-keyserver cold-starts, ISP-vs-CDN disambiguation, live-sports buffering, player-startup regressions on a cross-platform release, and encoder ABR ladder switchovers.