From 195e25437a46e712b1e3eec5ea4d1d7de6b9338d Mon Sep 17 00:00:00 2001 From: Dariusz L Date: Wed, 2 Jul 2025 10:36:22 +0200 Subject: [PATCH] Improve matting error handling and user feedback Adds checks for missing 'transformers' dependency and network errors in the matting endpoint, returning clear error messages for common failure cases. Updates the frontend to display more informative alerts to users when matting fails, including details from server responses. --- canvas_node.py | 41 ++++++++++++++++++++++++++++++++--------- js/CanvasView.js | 12 +++++++++--- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/canvas_node.py b/canvas_node.py index f94c000..09d8fa8 100644 --- a/canvas_node.py +++ b/canvas_node.py @@ -10,7 +10,12 @@ import threading import os from tqdm import tqdm from torchvision import transforms -from transformers import AutoModelForImageSegmentation, PretrainedConfig +try: + from transformers import AutoModelForImageSegmentation, PretrainedConfig + from requests.exceptions import ConnectionError as RequestsConnectionError + TRANSFORMERS_AVAILABLE = True +except ImportError: + TRANSFORMERS_AVAILABLE = False import torch.nn.functional as F import traceback import uuid @@ -712,25 +717,31 @@ _matting_lock = None async def matting(request): global _matting_lock + if not TRANSFORMERS_AVAILABLE: + log_error("Matting request failed: 'transformers' library is not installed.") + return web.json_response({ + "error": "Dependency Not Found", + "details": "The 'transformers' library is required for the matting feature. Please install it by running: pip install transformers" + }, status=400) + if _matting_lock is not None: log_warn("Matting already in progress, rejecting request") return web.json_response({ "error": "Another matting operation is in progress", "details": "Please wait for the current operation to complete" - }, status=429) # 429 Too Many Requests + }, status=429) _matting_lock = True - try: log_info("Received matting request") data = await request.json() - matting = BiRefNetMatting() + matting_instance = BiRefNetMatting() image_tensor, original_alpha = convert_base64_to_tensor(data["image"]) log_debug(f"Input image shape: {image_tensor.shape}") - matted_image, alpha_mask = matting.execute( + matted_image, alpha_mask = matting_instance.execute( image_tensor, "BiRefNet/model.safetensors", threshold=data.get("threshold", 0.5), @@ -745,14 +756,26 @@ async def matting(request): "alpha_mask": result_mask }) - except Exception as e: - log_exception(f"Error in matting endpoint: {str(e)}") + except RequestsConnectionError as e: + log_error(f"Connection error during matting model download: {e}") return web.json_response({ - "error": str(e), + "error": "Network Connection Error", + "details": "Failed to download the matting model from Hugging Face. Please check your internet connection." + }, status=400) + except Exception as e: + log_exception(f"Error in matting endpoint: {e}") + # Check for offline error message from Hugging Face + if "Offline mode is enabled" in str(e) or "Can't load 'ZhengPeng7/BiRefNet' offline" in str(e): + return web.json_response({ + "error": "Network Connection Error", + "details": "Failed to download the matting model from Hugging Face. Please check your internet connection and ensure you are not in offline mode." + }, status=400) + + return web.json_response({ + "error": "An unexpected error occurred", "details": traceback.format_exc() }, status=500) finally: - _matting_lock = None log_debug("Matting lock released") diff --git a/js/CanvasView.js b/js/CanvasView.js index ac1c080..fdddcb4 100644 --- a/js/CanvasView.js +++ b/js/CanvasView.js @@ -826,9 +826,15 @@ async function createCanvasWidget(node, widget, app) { body: JSON.stringify({image: imageData}) }); - if (!response.ok) throw new Error(`Server error: ${response.status} - ${response.statusText}`); - const result = await response.json(); + + if (!response.ok) { + let errorMsg = `Server error: ${response.status} - ${response.statusText}`; + if (result && result.error) { + errorMsg = `Error: ${result.error}\n\nDetails: ${result.details}`; + } + throw new Error(errorMsg); + } const mattedImage = new Image(); mattedImage.src = result.matted_image; await mattedImage.decode(); @@ -840,7 +846,7 @@ async function createCanvasWidget(node, widget, app) { canvas.saveState(); } catch (error) { log.error("Matting error:", error); - alert(`Error during matting process: ${error.message}`); + alert(`Matting process failed:\n\n${error.message}`); } finally { button.classList.remove('loading'); button.removeChild(spinner);