From 443a9b78d7315cf141e18f6779cf810b1595c1ea Mon Sep 17 00:00:00 2001 From: Sameer6305 Date: Thu, 23 Jul 2026 15:09:44 +0530 Subject: [PATCH] Fix #770: Explorer backend routes return proper error status codes instead of 200 OK on failure - routes/temporal.py: temporal_patterns raises HTTPException(500) instead of silently returning an empty-but-valid TemporalPatternResponse on exception - routes/analytics.py: preserves existing partial-success body shape (frontend already parses this), but sets response.status_code = 207 when any individual metric computation fails, so callers get a real signal instead of an indistinguishable 200 - routes/ontology.py: POST /create now raises HTTPException(500) on generation failure instead of silently falling back to a partial/minimal ontology and returning 200 with a misleading nodes_added count Verified via git stash comparison that pre-existing test suite failures (58 errors, Starlette TestClient/httpx version mismatch) are unrelated to this change - identical failure count on modified and unmodified code. Closes #770 --- semantica/explorer/routes/analytics.py | 12 ++++++++++-- semantica/explorer/routes/ontology.py | 2 ++ semantica/explorer/routes/temporal.py | 6 +++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/semantica/explorer/routes/analytics.py b/semantica/explorer/routes/analytics.py index 1b8b13f9..39d08e5a 100644 --- a/semantica/explorer/routes/analytics.py +++ b/semantica/explorer/routes/analytics.py @@ -1,11 +1,11 @@ -""" +""" Analytics routes for graph metrics and validation. """ import asyncio from typing import Optional -from fastapi import APIRouter, Depends, Query +from fastapi import APIRouter, Depends, Query, HTTPException, Response from ..dependencies import get_session from ..schemas import AnalyticsResponse, ValidationIssue, ValidationReportResponse @@ -16,6 +16,7 @@ router = APIRouter(prefix="/api/analytics", tags=["Analytics"]) @router.get("", response_model=AnalyticsResponse) async def get_analytics( + response: Response, metrics: Optional[str] = Query( None, description="Comma-separated metrics to compute: centrality,community,connectivity", @@ -25,6 +26,7 @@ async def get_analytics( requested = set((metrics or "centrality,community,connectivity").split(",")) graph_dict = await asyncio.to_thread(session.build_graph_dict) result: dict = {} + any_failed = False if "centrality" in requested and session.centrality is not None: try: @@ -34,6 +36,7 @@ async def get_analytics( ) except Exception as exc: result["centrality"] = {"error": str(exc)} + any_failed = True if "community" in requested and session.community is not None: try: @@ -43,6 +46,7 @@ async def get_analytics( ) except Exception as exc: result["community"] = {"error": str(exc)} + any_failed = True if "connectivity" in requested and session.connectivity is not None: try: @@ -52,6 +56,10 @@ async def get_analytics( ) except Exception as exc: result["connectivity"] = {"error": str(exc)} + any_failed = True + + if any_failed: + response.status_code = 207 return AnalyticsResponse(**result) diff --git a/semantica/explorer/routes/ontology.py b/semantica/explorer/routes/ontology.py index 411a6bb4..6ce0470f 100644 --- a/semantica/explorer/routes/ontology.py +++ b/semantica/explorer/routes/ontology.py @@ -1402,6 +1402,7 @@ async def create_ontology( except Exception as exc: logger.exception("Failed to generate ontology from sample data; falling back to minimal ontology.") logger.warning(f"OntologyEngine.from_data error: {exc}") + raise HTTPException(status_code=500, detail=str(exc)) elif body.mode == "text" and body.schema_text: try: @@ -1472,6 +1473,7 @@ async def create_ontology( except Exception as exc: logger.exception("Failed to generate ontology from schema text; falling back to minimal ontology.") logger.warning(f"OntologyEngine.from_text error: {exc}") + raise HTTPException(status_code=500, detail=str(exc)) nodes_added = await asyncio.to_thread(session.add_nodes, nodes) edges_added = await asyncio.to_thread(session.add_edges, edges) diff --git a/semantica/explorer/routes/temporal.py b/semantica/explorer/routes/temporal.py index 31cca479..71c47e52 100644 --- a/semantica/explorer/routes/temporal.py +++ b/semantica/explorer/routes/temporal.py @@ -1,4 +1,4 @@ -""" +""" Temporal routes for snapshots, diffs, and pattern detection. """ @@ -8,7 +8,7 @@ import re from datetime import datetime, timedelta, timezone, UTC from typing import List, Optional -from fastapi import APIRouter, Depends, Query +from fastapi import APIRouter, Depends, Query, HTTPException from pydantic import BaseModel from ..dependencies import get_session @@ -117,7 +117,7 @@ async def temporal_patterns( return TemporalPatternResponse(patterns=[]) except Exception as exc: logger.warning("temporal_patterns failed: %s", exc, exc_info=True) - return TemporalPatternResponse(patterns=[]) + raise HTTPException(status_code=500, detail=str(exc)) @router.get("/bounds", response_model=TemporalBoundsResponse)