Browse Source

fix: video regeneration spinner stuck + cancel error message

Fix video element not reloading on regeneration by adding key prop tied
to video history ID. Fix cancel showing timeout message by passing
"user-cancelled" reason through AbortController and checking it in all
three executor catch blocks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 5 months ago
parent
commit
4dde7acf6a
  1. 1
      src/components/nodes/GenerateVideoNode.tsx
  2. 5
      src/store/execution/generateVideoExecutor.ts
  3. 19
      src/store/execution/llmGenerateExecutor.ts
  4. 5
      src/store/execution/nanoBananaExecutor.ts
  5. 2
      src/store/workflowStore.ts

1
src/components/nodes/GenerateVideoNode.tsx

@ -592,6 +592,7 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps<GenerateVide
<> <>
<div className="relative w-full flex-1 min-h-0"> <div className="relative w-full flex-1 min-h-0">
<video <video
key={nodeData.videoHistory?.[nodeData.selectedVideoHistoryIndex || 0]?.id}
src={nodeData.outputVideo} src={nodeData.outputVideo}
controls controls
autoPlay autoPlay

5
src/store/execution/generateVideoExecutor.ts

@ -195,7 +195,10 @@ export async function executeGenerateVideo(
} catch (error) { } catch (error) {
let errorMessage = "Video generation failed"; let errorMessage = "Video generation failed";
if (error instanceof DOMException && error.name === "AbortError") { if (error instanceof DOMException && error.name === "AbortError") {
errorMessage = "Request timed out. Video generation may take longer."; const isUserCancel = signal?.reason === "user-cancelled";
errorMessage = isUserCancel
? "Generation cancelled."
: "Request timed out. Video generation may take longer.";
} else if (error instanceof TypeError && error.message.includes("NetworkError")) { } else if (error instanceof TypeError && error.message.includes("NetworkError")) {
errorMessage = "Network error. Check your connection and try again."; errorMessage = "Network error. Check your connection and try again.";
} else if (error instanceof TypeError) { } else if (error instanceof TypeError) {

19
src/store/execution/llmGenerateExecutor.ts

@ -107,11 +107,24 @@ export async function executeLlmGenerate(
throw new Error(result.error || "LLM generation failed"); throw new Error(result.error || "LLM generation failed");
} }
} catch (error) { } catch (error) {
let errorMessage = "LLM generation failed";
if (error instanceof DOMException && error.name === "AbortError") {
const isUserCancel = signal?.reason === "user-cancelled";
errorMessage = isUserCancel
? "Generation cancelled."
: "Request timed out. Try using a simpler prompt.";
} else if (error instanceof TypeError && error.message.includes("NetworkError")) {
errorMessage = "Network error. Check your connection and try again.";
} else if (error instanceof TypeError) {
errorMessage = `Network error: ${error.message}`;
} else if (error instanceof Error) {
errorMessage = error.message;
}
updateNodeData(node.id, { updateNodeData(node.id, {
status: "error", status: "error",
error: error instanceof Error ? error.message : "LLM generation failed", error: errorMessage,
}); });
if (error instanceof DOMException && error.name === "AbortError") throw error; throw error instanceof Error ? error : new Error(errorMessage);
throw error instanceof Error ? error : new Error("LLM generation failed");
} }
} }

5
src/store/execution/nanoBananaExecutor.ts

@ -214,7 +214,10 @@ export async function executeNanoBanana(
// Convert network/abort errors to user-friendly messages // Convert network/abort errors to user-friendly messages
let errorMessage = "Generation failed"; let errorMessage = "Generation failed";
if (error instanceof DOMException && error.name === "AbortError") { if (error instanceof DOMException && error.name === "AbortError") {
errorMessage = "Request timed out. Try reducing image sizes or using a simpler prompt."; const isUserCancel = signal?.reason === "user-cancelled";
errorMessage = isUserCancel
? "Generation cancelled."
: "Request timed out. Try reducing image sizes or using a simpler prompt.";
} else if (error instanceof TypeError && error.message.includes("NetworkError")) { } else if (error instanceof TypeError && error.message.includes("NetworkError")) {
errorMessage = "Network error. Check your connection and try again."; errorMessage = "Network error. Check your connection and try again.";
} else if (error instanceof TypeError) { } else if (error instanceof TypeError) {

2
src/store/workflowStore.ts

@ -967,7 +967,7 @@ export const useWorkflowStore = create<WorkflowStore>((set, get) => ({
// Abort any in-flight requests // Abort any in-flight requests
const controller = get()._abortController; const controller = get()._abortController;
if (controller) { if (controller) {
controller.abort(); controller.abort("user-cancelled");
} }
set({ isRunning: false, currentNodeIds: [], _abortController: null }); set({ isRunning: false, currentNodeIds: [], _abortController: null });
}, },

Loading…
Cancel
Save