diff --git a/app.py b/app.py index 8d84a1940..75aac8ebe 100644 --- a/app.py +++ b/app.py @@ -331,8 +331,8 @@ if AUTH_ENABLED: request.state.current_user = "internal-tool" request.state.api_token = False return await call_next(request) - except Exception: - pass + except Exception as _e: + logger.warning("Internal tool auth header check failed", exc_info=_e) # Allow DIRECT localhost requests (internal service calls from # heartbeats etc.). Tunnel/proxy-forwarded requests are excluded by # _is_trusted_loopback so LOCALHOST_BYPASS can't be abused over a @@ -385,11 +385,10 @@ if AUTH_ENABLED: _db.close() try: await _asyncio.to_thread(_do) - except Exception: - pass + except Exception as _e: + logger.debug("Failed to update token last_used_at", exc_info=_e) _asyncio.create_task(_touch_last_used(matched_id)) # Keep bearer-token callers out of normal cookie/user - # routes. API-aware routes can read api_token_owner. request.state.current_user = "api" request.state.api_token = True request.state.api_token_id = matched_id @@ -464,8 +463,8 @@ async def serve_generated_image(filename: str, request: Request): _db.close() except HTTPException: raise - except Exception: - pass + except Exception as _e: + logger.warning("Image ownership verification failed for %r", filename, exc_info=_e) ext = filename.rsplit('.', 1)[-1].lower() mime = { "png": "image/png", "jpg": "image/jpeg", "jpeg": "image/jpeg", diff --git a/routes/chat_routes.py b/routes/chat_routes.py index c33f7c2c7..b464eac8f 100644 --- a/routes/chat_routes.py +++ b/routes/chat_routes.py @@ -126,7 +126,8 @@ def _clear_orphaned_session_endpoint(sess, owner: str | None = None) -> bool: sess.model = "" sess.headers = {} return True - except Exception: + except Exception as e: + logger.warning("Failed to clear orphaned session endpoint", exc_info=e) db.rollback() return False finally: @@ -144,7 +145,8 @@ def _endpoint_cache_contains_model(endpoint, model: str) -> bool: return True try: models = json.loads(raw) if isinstance(raw, str) else raw - except Exception: + except Exception as e: + logger.warning("Failed to parse cached models list, treating as containing model", exc_info=e) return True if not isinstance(models, list) or not models: return True @@ -236,7 +238,8 @@ def _recover_empty_session_model(sess, session_id: str, owner: str | None = None is_chatgpt_subscription = False try: cached = json.loads(ep.cached_models) if isinstance(ep.cached_models, str) else (ep.cached_models or []) - except Exception: + except Exception as e: + logger.warning("Failed to parse cached_models for endpoint %r", getattr(ep, "id", "?"), exc_info=e) cached = [] if not cached: visible = [] @@ -646,8 +649,8 @@ def setup_chat_routes( elif attachments: try: att_ids = [str(x) for x in json.loads(attachments)] - except Exception: - pass + except Exception as e: + logger.warning("Failed to parse attachments JSON, ignoring attachments", exc_info=e) no_memory = str(form_data.get("no_memory", "")).lower() == "true" pre_context_tool_policy = build_effective_tool_policy( diff --git a/routes/document_routes.py b/routes/document_routes.py index e4598d925..22434c61a 100644 --- a/routes/document_routes.py +++ b/routes/document_routes.py @@ -503,7 +503,8 @@ def setup_document_routes(session_manager, upload_handler=None) -> APIRouter: user = get_current_user(request) try: data = await request.json() - except Exception: + except Exception as e: + logger.warning("Failed to parse export request body, defaulting to empty", exc_info=e) data = {} ids = data.get("ids") or [] if not ids: @@ -645,8 +646,8 @@ def setup_document_routes(session_manager, upload_handler=None) -> APIRouter: try: from src.agent_tools.document_tools import clear_active_document clear_active_document(doc_id) - except Exception: - pass + except Exception as e: + logger.warning("Failed to clear active document %r on detach", doc_id, exc_info=e) db.commit() db.refresh(doc) return _doc_to_dict(doc) diff --git a/routes/email_routes.py b/routes/email_routes.py index 0f4af19ae..b95d38f3e 100644 --- a/routes/email_routes.py +++ b/routes/email_routes.py @@ -79,15 +79,16 @@ def _email_tag_owner_aliases(account_id: str | None, owner: str = "") -> list[st cfg.get("smtp_user") or "", cfg.get("from_address") or "", ]) - except Exception: + except Exception as _e: + logger.warning("Failed to resolve email account alias", exc_info=_e) resolved_account_id = None row = db.get(_EA, resolved_account_id) if resolved_account_id else None if row: aliases.extend([row.owner or "", row.imap_user or "", row.from_address or ""]) finally: db.close() - except Exception: - pass + except Exception as _e: + logger.warning("Failed to load email aliases", exc_info=_e) out = [] for a in aliases: a = (a or "").strip() diff --git a/src/agent_loop.py b/src/agent_loop.py index f600ac598..c3f100f73 100644 --- a/src/agent_loop.py +++ b/src/agent_loop.py @@ -524,7 +524,7 @@ def get_builtin_overrides() -> dict: ov = get_setting("builtin_tool_overrides", {}) return ov if isinstance(ov, dict) else {} except Exception as e: - logger.warning('Failed to load builtin tool overrides: %s', e) + logger.warning("Failed to load builtin tool overrides, using defaults", exc_info=e) return {} @@ -929,8 +929,8 @@ def _build_system_prompt( try: from src.user_time import current_datetime_context_message _datetime_message = current_datetime_context_message() - except Exception: - pass + except Exception as e: + logger.warning("Failed to build datetime context message", exc_info=e) # Document context is kept as a SEPARATE message (not merged into the tool # prompt) so the context trimmer doesn't destroy it when truncating the @@ -973,8 +973,8 @@ def _build_system_prompt( try: from src.pdf_form_doc import find_source_upload_id _is_form_backed = bool(find_source_upload_id(active_document.current_content or "")) - except Exception: - pass + except Exception as e: + logger.warning("Failed to detect if document is form-backed, assuming plain", exc_info=e) if _is_form_backed: doc_ctx = ( diff --git a/src/llm_core.py b/src/llm_core.py index 1338ef91a..e809d7968 100644 --- a/src/llm_core.py +++ b/src/llm_core.py @@ -283,7 +283,8 @@ def _is_ollama_native_url(url: str) -> bool: """Return True for native Ollama API URLs, including Ollama Cloud.""" try: parsed = urlparse(url or "") - except Exception: + except Exception as e: + logger.warning("Failed to parse URL for Ollama detection", exc_info=e) return False host = parsed.hostname or "" path = (parsed.path or "").rstrip("/") @@ -1345,8 +1346,8 @@ def list_model_ids( r = httpx.get(root + "/api/tags", timeout=timeout) r.raise_for_status() return [m.get("name") or m.get("model") for m in (r.json().get("models") or []) if m.get("name") or m.get("model")] - except Exception: - pass + except Exception as e: + logger.warning("Failed to fetch model list from configured endpoint", exc_info=e) return [] def normalize_model_id(