diff --git a/app.py b/app.py index 9401927e0..75aac8ebe 100644 --- a/app.py +++ b/app.py @@ -332,7 +332,7 @@ if AUTH_ENABLED: request.state.api_token = False return await call_next(request) except Exception as _e: - logger.warning("Internal tool auth header check failed: %s", _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 @@ -386,7 +386,7 @@ if AUTH_ENABLED: try: await _asyncio.to_thread(_do) except Exception as _e: - logger.debug("Failed to update token last_used_at: %s", _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 request.state.current_user = "api" @@ -464,7 +464,7 @@ async def serve_generated_image(filename: str, request: Request): except HTTPException: raise except Exception as _e: - logger.warning("Image ownership verification failed for %r: %s", filename, _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 8f80ca4db..b464eac8f 100644 --- a/routes/chat_routes.py +++ b/routes/chat_routes.py @@ -127,7 +127,7 @@ def _clear_orphaned_session_endpoint(sess, owner: str | None = None) -> bool: sess.headers = {} return True except Exception as e: - logger.warning("Failed to clear orphaned session endpoint: %s", e) + logger.warning("Failed to clear orphaned session endpoint", exc_info=e) db.rollback() return False finally: @@ -146,7 +146,7 @@ def _endpoint_cache_contains_model(endpoint, model: str) -> bool: try: models = json.loads(raw) if isinstance(raw, str) else raw except Exception as e: - logger.warning("Failed to parse cached models list, treating as containing model: %s", 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 @@ -239,7 +239,7 @@ def _recover_empty_session_model(sess, session_id: str, owner: str | None = None try: cached = json.loads(ep.cached_models) if isinstance(ep.cached_models, str) else (ep.cached_models or []) except Exception as e: - logger.warning("Failed to parse cached_models for endpoint %r: %s", getattr(ep, "id", "?"), e) + logger.warning("Failed to parse cached_models for endpoint %r", getattr(ep, "id", "?"), exc_info=e) cached = [] if not cached: visible = [] @@ -650,7 +650,7 @@ def setup_chat_routes( try: att_ids = [str(x) for x in json.loads(attachments)] except Exception as e: - logger.warning("Failed to parse attachments JSON, ignoring attachments: %s", 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 a7f786743..22434c61a 100644 --- a/routes/document_routes.py +++ b/routes/document_routes.py @@ -504,7 +504,7 @@ def setup_document_routes(session_manager, upload_handler=None) -> APIRouter: try: data = await request.json() except Exception as e: - logger.warning("Failed to parse export request body, defaulting to empty: %s", e) + logger.warning("Failed to parse export request body, defaulting to empty", exc_info=e) data = {} ids = data.get("ids") or [] if not ids: @@ -647,7 +647,7 @@ def setup_document_routes(session_manager, upload_handler=None) -> APIRouter: from src.agent_tools.document_tools import clear_active_document clear_active_document(doc_id) except Exception as e: - logger.warning("Failed to clear active document %r on detach: %s", doc_id, 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 7c332ca98..b95d38f3e 100644 --- a/routes/email_routes.py +++ b/routes/email_routes.py @@ -80,7 +80,7 @@ def _email_tag_owner_aliases(account_id: str | None, owner: str = "") -> list[st cfg.get("from_address") or "", ]) except Exception as _e: - logger.warning("Failed to resolve email account alias: %s", _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: @@ -88,7 +88,7 @@ def _email_tag_owner_aliases(account_id: str | None, owner: str = "") -> list[st finally: db.close() except Exception as _e: - logger.warning("Failed to load email aliases: %s", _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 3e1963ee6..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, using defaults: %s", e) + logger.warning("Failed to load builtin tool overrides, using defaults", exc_info=e) return {} @@ -974,7 +974,7 @@ def _build_system_prompt( 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 as e: - logger.warning("Failed to detect if document is form-backed, assuming plain: %s", 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 cbfbeb834..9cd131c69 100644 --- a/src/llm_core.py +++ b/src/llm_core.py @@ -284,7 +284,7 @@ def _is_ollama_native_url(url: str) -> bool: try: parsed = urlparse(url or "") except Exception as e: - logger.warning("Failed to parse URL for Ollama detection %r: %s", url, e) + logger.warning("Failed to parse URL for Ollama detection %r", url, exc_info=e) return False host = parsed.hostname or "" path = (parsed.path or "").rstrip("/") @@ -1347,7 +1347,7 @@ def list_model_ids( 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 as e: - logger.warning("Failed to fetch model list from endpoint %r: %s", base_chat_url, e) + logger.warning("Failed to fetch model list from endpoint %r", base_chat_url, exc_info=e) return [] def normalize_model_id(