Defect
providers/tf-mediapipe/src/ai/common/TFMP_Runtime.ts caches built MediaPipe task instances by model_path + matched options, but the cache check and the insertion are separated by an await, with nothing recording the in-flight build.
TFMP_Runtime.ts:238-246:
const cachedTasks = modelTaskCache.get(model_path);
if (cachedTasks) {
const matchedTask = cachedTasks.find((cached) => optionsMatch(cached.options, lookupOptions));
if (matchedTask) {
return matchedTask.task;
}
}
const wasmFileset = await getWasmTask(model, emit, signal); // ← yields
…and the result is only published at :271:
modelTaskCache.get(model_path)!.push(cachedTask);
Two concurrent callers with the same model_path and matching options both reach :238 before either reaches :271. Both miss, both download/instantiate, and one of the two built tasks is orphaned in the cache list — holding a WebGPU/WASM handle nothing will ever dispose.
Evidence
providers/tf-mediapipe/src/ai/common/TFMP_Runtime.ts:238-246 — check
providers/tf-mediapipe/src/ai/common/TFMP_Runtime.ts:271 — publish
- No in-flight map:
grep -n "InFlight\|inFlight\|pending" providers/tf-mediapipe/src/ai/common/TFMP_Runtime.ts finds nothing on this path.
The package already contains the correct pattern for its sibling runtime — TFMP_GenaiRuntime.ts uses withGenaiLock / isGenaiBusy — and the cactus provider has the shape too (cactusEngineLoadsInFlight, referenced in providers/cactus/src/ai.ts's export comment). This is a copy of an in-tree pattern, not a new design.
Proposed fix
Add a Map<string, Promise<TaskInstance>> keyed the same way the cache is, populated before the first await and cleared in finally; return the shared promise on a hit. ~15 LOC.
Why it matters
Every vision run-fn in the package goes through getModelTask, and a fanned-out graph (MapTask over N images) hits it N times concurrently by construction. On a WebGPU delegate the duplicate build is a second GPU context and a second copy of the model weights, with the loser leaked for the process lifetime.
Carried as a review finding for five cycles (2026-08-03 onward) without being tracked. The 2026-08-31 window touched nine other files in this package (388a2b8, 9ada0ea) and not this one. Filing it. Snapshot: workglow-dev/prd → analysis/grades/2026-08-31/libs-providers.md.
Defect
providers/tf-mediapipe/src/ai/common/TFMP_Runtime.tscaches built MediaPipe task instances bymodel_path+ matched options, but the cache check and the insertion are separated by anawait, with nothing recording the in-flight build.TFMP_Runtime.ts:238-246:…and the result is only published at
:271:Two concurrent callers with the same
model_pathand matching options both reach:238before either reaches:271. Both miss, both download/instantiate, and one of the two built tasks is orphaned in the cache list — holding a WebGPU/WASM handle nothing will ever dispose.Evidence
providers/tf-mediapipe/src/ai/common/TFMP_Runtime.ts:238-246— checkproviders/tf-mediapipe/src/ai/common/TFMP_Runtime.ts:271— publishgrep -n "InFlight\|inFlight\|pending" providers/tf-mediapipe/src/ai/common/TFMP_Runtime.tsfinds nothing on this path.The package already contains the correct pattern for its sibling runtime —
TFMP_GenaiRuntime.tsuseswithGenaiLock/isGenaiBusy— and the cactus provider has the shape too (cactusEngineLoadsInFlight, referenced inproviders/cactus/src/ai.ts's export comment). This is a copy of an in-tree pattern, not a new design.Proposed fix
Add a
Map<string, Promise<TaskInstance>>keyed the same way the cache is, populated before the firstawaitand cleared infinally; return the shared promise on a hit. ~15 LOC.Why it matters
Every vision run-fn in the package goes through
getModelTask, and a fanned-out graph (MapTaskover N images) hits it N times concurrently by construction. On a WebGPU delegate the duplicate build is a second GPU context and a second copy of the model weights, with the loser leaked for the process lifetime.Carried as a review finding for five cycles (2026-08-03 onward) without being tracked. The 2026-08-31 window touched nine other files in this package (
388a2b8,9ada0ea) and not this one. Filing it. Snapshot:workglow-dev/prd→analysis/grades/2026-08-31/libs-providers.md.