commit 909ba617994953364553651c1d40873566c39c43
parent eb5ba0f4866406ce042919f8388e7c33b7d9d1df
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Fri, 11 Sep 2026 11:44:31 -0400
editor: the one path to a channel's media that no job record covers
saveShardConfigAction calls runYtdlp / runWhisperBatch / runAvailabilityCheck
directly, with no job record, so the guard in runManagedFunction has never seen
it. What that costs on an unmounted drive is not a failed save but a confident
wrong one: each runner computes its slice over the population it finds on disk,
an unreachable data/ makes that "every video is missing", and the resulting
shard — which says the whole channel needs re-downloading — is written to disk
and outlives the mount long enough for another machine to act on it. A shard is
exactly the artifact you do not want silently wrong.
The assert is at the top of the function rather than in the download branch the
plan named: all three branches read the same dirs for the same reason.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat:
1 file changed, 22 insertions(+), 0 deletions(-)
diff --git a/editor/app/channels/[slug]/shardActions.ts b/editor/app/channels/[slug]/shardActions.ts
@@ -9,6 +9,7 @@ import {
type ShardOp,
} from "yt-dlp-transcript-common/controller/shard";
import { readChannelConfig } from "yt-dlp-transcript-common/controller/channels";
+import { assertChannelMediaReachable } from "yt-dlp-transcript-common/lib/channelMedia";
import { runYtdlp } from "yt-dlp-transcript-common/ytdlp/runYtdlp";
import { runWhisperBatch } from "yt-dlp-transcript-common/controller/whisperBatch";
import { runAvailabilityCheck } from "yt-dlp-transcript-common/controller/checkAvailability";
@@ -68,6 +69,27 @@ export async function saveShardConfigAction(
const noopLog = () => {};
const signal = new AbortController().signal;
+ // THE ONE TRUE BYPASS (plans/relocate-channel-media.md). Every other path to a
+ // channel's media goes through runManagedFunction and is covered by the guard
+ // there; all three branches below call their runner DIRECTLY, with no job
+ // record, so nothing upstream has checked anything.
+ //
+ // What that costs on an unmounted drive is not a failed save, it is a
+ // confident wrong one: each runner computes its slice over the population it
+ // finds on disk (all video dirs / the post-prefilter missing set / the data
+ // dirs), and an unreachable data/ makes that "every video is missing". The
+ // saved slice then says the whole channel needs re-downloading, is written to
+ // disk, and outlives the mount long enough for another machine to act on it.
+ // A shard is precisely the artifact you do not want silently wrong.
+ //
+ // It is at the top rather than in the download branch alone because all three
+ // read the same dirs for the same reason.
+ try {
+ await assertChannelMediaReachable(paths, slug);
+ } catch (e) {
+ return { ok: false, error: (e as Error).message };
+ }
+
try {
if (op === "transcribe-missing") {
await runWhisperBatch({