From f950c22a595dd5ae0eecd4878c9600976ef9b308 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 26 Mar 2026 12:16:07 -0400 Subject: [PATCH] fix(clip-video): correct false 'Clipped' state on network failure + error UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_object() returns false on network failure; the .then() handler was running with result=false and accessing result.hosted_file_id (evaluates to undefined, valid JS key, no throw) so all success state was set even though the request failed. - Guard result in .then(): if !result.hosted_file_id → set status='error' - Add 'Failed — Retry?' button state in error branch - Raise client-side AbortController timeout 300s → 1800s (30 min) - Add comment explaining root cause (get_object returns false, not throw) Root cause of the connection drop is proxy_send_timeout or NAT hairpin timeout (both default 60s) — not a frontend issue; tracked separately. Co-Authored-By: Claude Sonnet 4.6 --- .../ae_comp__hosted_files_clip_video.svelte | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte b/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte index a0691646..d251042b 100644 --- a/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte +++ b/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte @@ -147,7 +147,7 @@ function handle_clip_video(event: Event) { api_cfg: $ae_api, endpoint: endpoint, params: params, - timeout: 300000, // 5 minutes + timeout: 1800000, // 30 minutes — clip_video runs ffmpeg which can take 5-15 min for long recordings // return_blob: true, // filename: event.target.new_filename.value, // auto_download: false, @@ -157,12 +157,24 @@ function handle_clip_video(event: Event) { .then(function (result) { console.log(result); + // WHY: get_object() returns false/null on network failure (CORS drop, + // timeout, Gunicorn worker killed). Without this guard, result.hosted_file_id + // is undefined — JS uses it as an object key without throwing, so all the + // success state below would run and show "Clipped" on a failed request. + if (!result || !result.hosted_file_id) { + console.log('clip_video: request failed or returned no result'); + $ae_sess.files.processed_file_kv[hosted_file_id].submit_status = + 'error'; + $ae_loc.files.processed_file_kv[hosted_file_id].submit_status = + 'error'; + submit_status = 'error'; + clip_complete = false; + return false; + } + video_clip_file_kv[result.hosted_file_id] = {}; video_clip_file_kv[result.hosted_file_id] = result; - // $ae_loc.files.video_clip_file_kv[result.hosted_file_id] = {}; - // $ae_loc.files.video_clip_file_kv[result.hosted_file_id] = result; - $ae_sess.files.processed_file_kv[hosted_file_id].submit_status = 'clipped'; $ae_sess.files.processed_file_kv[hosted_file_id].clip_complete = @@ -176,13 +188,6 @@ function handle_clip_video(event: Event) { submit_status = 'clipped'; clip_complete = true; - // let file_blob = new Blob([result.data]); - // // console.log(file_blob); - // let file_obj_url = window.URL.createObjectURL(file_blob); // The img src - // // const url = window.URL.createObjectURL(new Blob([result.data])); - // download_clip_src = file_obj_url; - // // download_filename = file_obj_url; - return true; }); } @@ -363,21 +368,25 @@ function handle_clip_video(event: Event) {