Skip to content

fix: stop 13 routes from leaking internal errors (OPE-79)#254

Merged
DevanshuNEU merged 2 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:fix/stop-leaking-internal-errors
Feb 23, 2026
Merged

fix: stop 13 routes from leaking internal errors (OPE-79)#254
DevanshuNEU merged 2 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:fix/stop-leaking-internal-errors

Conversation

@DevanshuNEU

@DevanshuNEU DevanshuNEU commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

13 route handlers returned detail=str(e) in HTTP 500 responses. In production this leaked:

  • Pinecone connection strings and endpoints
  • Internal file paths (/srv/repos/...)
  • Git credential fragments
  • Database error messages
  • Third-party API error details

Fix

All 13 catch blocks now return generic error messages. The actual error is logged to Sentry/stdout for debugging.

File Instances Additional fix
analysis.py 5 Added except HTTPException: raise (was swallowing 404s as 500s) + added logging (had zero)
repos.py 4 Detail text only
search.py 2 Detail text only
search_v2.py 1 Detail text only
playground.py 1 Detail text only

Secondary bug fixed

analysis.py had a hidden bug: get_repo_or_404() raises HTTPException(404) but the bare except Exception was catching it and re-wrapping as a 500. Users requesting a non-existent repo got 500 Internal Server Error instead of 404 Not Found. Fixed by adding except HTTPException: raise before except Exception on all 5 analysis endpoints.

Tests

3 new tests verify that internal details (Pinecone URLs, file paths, git credentials) are NOT exposed in error responses.

284 tests pass (281 existing + 3 new).

Closes OPE-79

Summary by CodeRabbit

  • Bug Fixes

    • Standardized error responses across API endpoints with generic messages instead of exposing raw exception details.
    • Enhanced error handling with structured logging and telemetry capture on failures.
  • Tests

    • Added test coverage to verify error responses do not leak sensitive information in error messages.

Before: 13 route handlers returned raw exception strings in HTTP
responses. In production this leaked file paths, database connection
details, API key fragments, and third-party service errors.

After: All catch blocks return generic error messages. The actual
error is logged via logger.error() + capture_exception() for
debugging in Sentry/logs.

Changes by file:
- analysis.py: Fixed all 5 endpoints. Also added missing
  'except HTTPException: raise' (was swallowing 404s as 500s)
  and added logger.error + capture_exception (had zero logging).
- repos.py: Fixed 4 endpoints (add, delete, index, async index).
- search.py: Fixed 2 endpoints (search, explain).
- search_v2.py: Fixed 1 endpoint.
- playground.py: Fixed 1 endpoint.

Secondary fix in analysis.py:
- get_repo_or_404 raises HTTPException(404) but the bare
  'except Exception' was catching it and re-raising as 500.
  Added 'except HTTPException: raise' before 'except Exception'
  on all 5 endpoints.

Tests: 3 new tests verify that Pinecone connection strings, file
paths, and git credentials are NOT exposed in error responses.

284 tests pass (281 existing + 3 new).

Closes OPE-79
@vercel

vercel Bot commented Feb 23, 2026

Copy link
Copy Markdown

@DevanshuNEU is attempting to deploy a commit to the Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Feb 23, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Multiple backend API routes have been updated to standardize HTTP error responses and add observability instrumentation. Instead of exposing raw exception strings in 500 responses, endpoints now return generic error messages. New observability calls capture exceptions with contextual metadata. A test module validates that sensitive details aren't leaked in error responses.

Changes

Cohort / File(s) Summary
Error Handling Standardization
backend/routes/analysis.py
Added capture_exception import and instrumented error handlers across five endpoints (dependencies, impact, insights, style-analysis, dna) with structured logging, telemetry capture, and standardized error messages instead of raw exception strings.
Search and Playground Error Handling
backend/routes/playground.py, backend/routes/search.py, backend/routes/search_v2.py
Added capture_exception instrumentation in playground.py; standardized HTTP 500 error messages to generic strings ("Search failed", "Failed to fetch repository metadata", etc.) across all three files instead of exposing exception details.
Repository Management Error Handling
backend/routes/repos.py
Standardized HTTP 500 error messages for add_repository, delete_repository, index_repository, and related endpoints to return generic messages ("Failed to add repository", "Indexing failed", etc.) instead of exception strings.
Error Leaking Validation Tests
backend/tests/test_error_leaking.py
New test module with mocked internal services to verify that API endpoints return generic 500 error messages and do not leak sensitive details (e.g., Pinecone identifiers, file paths) in error responses.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through error paths so grand,
No secrets leaked, just messages so bland,
With telemetry snares and generic replies,
Internal details stay hidden from prying eyes! 🔐

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: stopping 13 routes from leaking internal errors, with a clear reference to the ticket (OPE-79).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@DevanshuNEU

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Feb 23, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
backend/routes/repos.py (2)

143-149: ⚠️ Potential issue | 🟠 Major

HTTP 400 is semantically wrong for a server-side failure — should be 500.

The exceptions reaching this catch block are git clone failures, disk errors, DB errors, etc. — all server faults. HTTP 400 signals a client fault ("Bad Request"), which will mislead callers, dashboards, and alerting rules that rely on 4xx vs 5xx classification. The companion test at test_error_leaking.py line 63 should be updated as well.

🔧 Proposed fix
-        raise HTTPException(status_code=400, detail="Failed to add repository")
+        raise HTTPException(status_code=500, detail="Failed to add repository")

In test_error_leaking.py:

-        assert resp.status_code == 400
+        assert resp.status_code == 500
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/repos.py` around lines 143 - 149, The catch-all exception
handler in backend/routes/repos.py currently converts server-side failures into
HTTPException(status_code=400) which is incorrect; update the handler in the
add-repository flow (the except Exception as e block that logs with logger.error
and calls capture_exception) to raise HTTPException(status_code=500,
detail="Failed to add repository") instead, keeping the existing logger.error
and capture_exception calls and leaving the earlier except HTTPException
re-raise intact; also update the corresponding expectation in
test_error_leaking.py (the assertion at the test around line 63) to expect a 500
response rather than 400.

388-400: ⚠️ Potential issue | 🟠 Major

Residual information-disclosure paths missed by this PR: WebSocket and Redis pub/sub both still send str(e) to clients.

Two pre-existing leaks remain unaddressed:

  1. websocket_index (line 576) sends the raw exception string directly to the WebSocket client:

    await websocket.send_json({"type": "error", "message": str(e)})
  2. _run_async_indexing (lines 393-400) publishes the raw exception string to the Redis pub/sub channel:

    publisher.publish_error(repo_id, error="indexing_failed", message=str(e), ...)

    Any WebSocket subscriber listening on that channel will receive the verbatim exception message.

Both are the same class of leak that OPE-79 targets (Pinecone endpoints, internal paths, git credential fragments can appear in exception strings).

🔧 Proposed fix sketch
# websocket_index (~line 576)
-        await websocket.send_json({"type": "error", "message": str(e)})
+        await websocket.send_json({"type": "error", "message": "Indexing failed"})

# _run_async_indexing (~line 397)
-            publisher.publish_error(repo_id, error="indexing_failed", message=str(e), recoverable=True)
+            publisher.publish_error(repo_id, error="indexing_failed", message="Indexing failed", recoverable=True)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/repos.py` around lines 388 - 400, The websocket and Redis
pub/sub still send raw exception strings to clients: in websocket_index
(websocket.send_json) and in _run_async_indexing (publisher.publish_error).
Replace str(e) usage with a non-sensitive, generic client-facing message (e.g.
"indexing_failed" or "An internal error occurred while indexing") or send an
error_id/token tied to the server-side log, while keeping the full exception
only in logger.error/capture_exception for internal diagnostics; update
websocket.send_json({... "message": ...}) and publisher.publish_error(...
message=...) accordingly and ensure logger.error/capture_exception continue to
record the original exception.
backend/routes/playground.py (2)

578-583: ⚠️ Potential issue | 🟠 Major

_fetch_repo_metadata still leaks str(e) to the HTTP response — missed by this PR.

At line 582 the raw exception is stored in the returned dict:

return {"error": "request_failed", "message": str(e)}

Both callers then put metadata.get("message", …) directly into an HTTP 502 response body:

  • validate_github_repo lines 700-703
  • start_anonymous_indexing lines 900-906

A Pinecone / DB / internal-network exception string becomes visible to the client through the 502.detail.message field, which is exactly the class of leak OPE-79 targets.

🔧 Proposed fix
-        except Exception as e:
-            logger.error("GitHub API request failed", error=str(e))
-            return {"error": "request_failed", "message": str(e)}
+        except Exception as e:
+            logger.error("GitHub API request failed", error=str(e))
+            return {"error": "request_failed", "message": "Failed to contact GitHub API"}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/playground.py` around lines 578 - 583, The
_fetch_repo_metadata function currently returns the raw exception string in
{"error": "request_failed", "message": str(e)}, which leaks internal errors to
clients; change it to return a non-sensitive, generic message (e.g. {"error":
"request_failed", "message": "failed to fetch repository metadata"}) and keep
the full exception in the server logs via logger.exception or logger.error with
the exception context. Update _fetch_repo_metadata (and related exception
handling) to avoid exposing str(e); callers validate_github_repo and
start_anonymous_indexing will then use metadata.get("message", ...) safely
without leaking internal details. Ensure httpx.TimeoutException still returns
the explicit timeout message while all other exceptions return the generic
message and the error is logged with traceback.

486-490: ⚠️ Potential issue | 🟡 Minor

Missing capture_exception call — inconsistent with the rest of the PR.

Every other updated handler (search.py, search_v2.py, repos.py, analysis.py) calls capture_exception before raising the generic 500. playground.py only logs to stdout, so failures here are invisible to Sentry.

🔧 Proposed fix
-from services.observability import logger
+from services.observability import logger, capture_exception
     except Exception as e:
         logger.error("Playground search failed", error=str(e))
+        capture_exception(e, operation="playground_search")
         raise HTTPException(status_code=500, detail="Search failed")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/playground.py` around lines 486 - 490, The except block in
playground.py currently only logs the error and raises HTTPException; add a call
to capture_exception(e) (as done in search.py/search_v2.py/repos.py/analysis.py)
before raising to ensure Sentry receives the failure; update the except
Exception as e handler in the Playground search handler to call
capture_exception(e) and then logger.error(...) and raise
HTTPException(status_code=500, detail="Search failed"); if capture_exception is
not already imported in this module, import it from the same location used by
the other handlers.
🧹 Nitpick comments (1)
backend/routes/analysis.py (1)

79-82: capture_exception in analyze_impact is missing the file_path context present in the logger.error call on the line above.

This means Sentry reports for impact-analysis failures won't include the file path, making them harder to reproduce. The explain_code handler in search.py (lines 173-179) consistently passes file_path to capture_exception.

♻️ Proposed fix
-        capture_exception(e, operation="impact_analysis", repo_id=repo_id)
+        capture_exception(e, operation="impact_analysis", repo_id=repo_id, file_path=request.file_path)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/analysis.py` around lines 79 - 82, The catch block in
analyze_impact is logging the error with file_path but calling capture_exception
without file_path, so Sentry events lack that context; update the
capture_exception call in the except block of analyze_impact (the same scope
where logger.error is called) to include file_path= request.file_path (match how
explain_code in search.py passes file_path) so Sentry receives the file_path
alongside operation="impact_analysis" and repo_id.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/tests/test_error_leaking.py`:
- Around line 47-66: The test currently only checks for a 400 and absence of
sensitive substrings, which can pass if InputValidator.validate_repo_name or
validate_git_url reject the request before repo_manager.add_repo is called;
update the test (test_repo_add_error_hides_details) to assert that
resp.json()["detail"] equals the exact generic error message that the route
returns when repo_manager.add_repo raises (the redacted message emitted by the
route's exception handler), and keep the repo_manager.add_repo side_effect in
place so the assertion guarantees the add_repo error path was exercised;
reference the validator functions InputValidator.validate_repo_name /
validate_git_url and the mocked repo_manager.add_repo to locate the relevant
behavior to pin the assertion to the canonical redacted message.
- Around line 9-26: The test can silently bypass the code path because
cache.get_search_results may return a hit; patch cache.get_search_results to
force a miss so indexer.semantic_search is invoked (e.g., patch the cache used
by routes.search so get_search_results returns None or an empty list) before
patching indexer.semantic_search; update the test_search_error_hides_details to
patch cache.get_search_results (or the cache object used by search_code) to
return a cache miss, then keep the existing patch of indexer.semantic_search to
raise the RuntimeError.

---

Outside diff comments:
In `@backend/routes/playground.py`:
- Around line 578-583: The _fetch_repo_metadata function currently returns the
raw exception string in {"error": "request_failed", "message": str(e)}, which
leaks internal errors to clients; change it to return a non-sensitive, generic
message (e.g. {"error": "request_failed", "message": "failed to fetch repository
metadata"}) and keep the full exception in the server logs via logger.exception
or logger.error with the exception context. Update _fetch_repo_metadata (and
related exception handling) to avoid exposing str(e); callers
validate_github_repo and start_anonymous_indexing will then use
metadata.get("message", ...) safely without leaking internal details. Ensure
httpx.TimeoutException still returns the explicit timeout message while all
other exceptions return the generic message and the error is logged with
traceback.
- Around line 486-490: The except block in playground.py currently only logs the
error and raises HTTPException; add a call to capture_exception(e) (as done in
search.py/search_v2.py/repos.py/analysis.py) before raising to ensure Sentry
receives the failure; update the except Exception as e handler in the Playground
search handler to call capture_exception(e) and then logger.error(...) and raise
HTTPException(status_code=500, detail="Search failed"); if capture_exception is
not already imported in this module, import it from the same location used by
the other handlers.

In `@backend/routes/repos.py`:
- Around line 143-149: The catch-all exception handler in
backend/routes/repos.py currently converts server-side failures into
HTTPException(status_code=400) which is incorrect; update the handler in the
add-repository flow (the except Exception as e block that logs with logger.error
and calls capture_exception) to raise HTTPException(status_code=500,
detail="Failed to add repository") instead, keeping the existing logger.error
and capture_exception calls and leaving the earlier except HTTPException
re-raise intact; also update the corresponding expectation in
test_error_leaking.py (the assertion at the test around line 63) to expect a 500
response rather than 400.
- Around line 388-400: The websocket and Redis pub/sub still send raw exception
strings to clients: in websocket_index (websocket.send_json) and in
_run_async_indexing (publisher.publish_error). Replace str(e) usage with a
non-sensitive, generic client-facing message (e.g. "indexing_failed" or "An
internal error occurred while indexing") or send an error_id/token tied to the
server-side log, while keeping the full exception only in
logger.error/capture_exception for internal diagnostics; update
websocket.send_json({... "message": ...}) and publisher.publish_error(...
message=...) accordingly and ensure logger.error/capture_exception continue to
record the original exception.

---

Nitpick comments:
In `@backend/routes/analysis.py`:
- Around line 79-82: The catch block in analyze_impact is logging the error with
file_path but calling capture_exception without file_path, so Sentry events lack
that context; update the capture_exception call in the except block of
analyze_impact (the same scope where logger.error is called) to include
file_path= request.file_path (match how explain_code in search.py passes
file_path) so Sentry receives the file_path alongside
operation="impact_analysis" and repo_id.

Comment thread backend/tests/test_error_leaking.py Outdated
Comment thread backend/tests/test_error_leaking.py Outdated
Code fixes:
1. repos.py add_repo: status 400 -> 500 (server failure, not client error)
2. repos.py _run_async_indexing: publisher.publish_error leaks str(e) to
   WebSocket clients. Now sends generic message.
3. repos.py websocket_index: send_json leaks str(e). Now generic.
4. playground.py _fetch_repo_metadata: returned raw str(e) in error dict.
   Now returns generic message, logs actual error.
5. playground.py search handler: added capture_exception (was missing entirely,
   not even imported).
6. analysis.py impact: added file_path to capture_exception kwargs
   (logger had it, Sentry didn't).

Test improvements:
7. test_repo_add: assert status 500 (was 400), assert exact detail text.
8. test_search: explicitly patch cache.get_search_results to return None
   instead of relying on conftest mock behavior.

284 tests pass.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
backend/tests/test_error_leaking.py (2)

6-7: Consider adding capture_exception patches to prevent unintended Sentry calls in tests.

If Sentry is initialized in CI (or becomes initialized later), these tests will fire real capture_exception calls. Patching it also lets you assert it was called with the expected args, strengthening the test.

♻️ Example for one test (apply same pattern to all three)
     def test_search_error_hides_details(self, client, valid_headers):
         """Search failure should not expose Pinecone/OpenAI error strings."""
         with patch("routes.search.indexer") as mock_indexer, \
-             patch("routes.search.cache") as mock_cache:
+             patch("routes.search.cache") as mock_cache, \
+             patch("routes.search.capture_exception") as mock_capture:
              mock_cache.get_search_results.return_value = None
              ...
+
+        mock_capture.assert_called_once()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/test_error_leaking.py` around lines 6 - 7, Patch out Sentry's
capture calls in these tests by mocking sentry_sdk.capture_exception (e.g., with
unittest.mock.patch or pytest monkeypatch) inside
TestErrorResponsesHideInternals (or each individual test) so tests don't call
real Sentry in CI; update the tests to assert the mock was called with the
expected exception/context and restore the original after the test. Locate the
tests in TestErrorResponsesHideInternals and wrap the request/handler invocation
with a patched capture_exception, or add a setup/teardown that applies the patch
for all three tests, then replace any direct assertions about external effects
with assertions against the mock.

1-68: Missing type hints on test method parameters.

Per the coding guidelines, backend/**/*.py files should have type hints on all function signatures. The test methods lack them on self, client, and valid_headers.

♻️ Example fix
-    def test_search_error_hides_details(self, client, valid_headers):
+    def test_search_error_hides_details(self, client: "TestClient", valid_headers: dict) -> None:

As per coding guidelines, backend/**/*.py: "Type hints on all function signatures in Python backend".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/test_error_leaking.py` around lines 1 - 68, The test methods
test_search_error_hides_details, test_dependency_graph_error_hides_details, and
test_repo_add_error_hides_details are missing type hints on their parameters;
add annotations (e.g., self: "TestErrorResponsesHideInternals", client:
TestClient or FlaskClient, valid_headers: dict[str, str]) to each signature and
import any needed typing (from typing import Dict or use built-in dict[str,
str]) so the file complies with the backend/**/*.py type-hint rule.
backend/routes/playground.py (1)

488-491: Minor: capture_exception is called before logger.error — reversed from all other handlers.

Every other error handler in this PR logs first, then captures (e.g., analysis.py Lines 43–44, repos.py Lines 146–147). Here the order is flipped. Not a bug, but inconsistent.

♻️ Suggested reorder for consistency
     except Exception as e:
-        capture_exception(e, operation="playground_search")
         logger.error("Playground search failed", error=str(e))
+        capture_exception(e, operation="playground_search")
         raise HTTPException(status_code=500, detail="Search failed")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/playground.py` around lines 488 - 491, In the playground error
handler for the playground_search operation, make the logging order consistent
with other handlers by calling logger.error(...) before capture_exception(...);
locate the except block that currently calls capture_exception(e,
operation="playground_search") then logger.error(...) and swap them so the error
is logged first (including the error string) and then capture_exception is
invoked, leaving the HTTPException raise unchanged.
backend/routes/repos.py (1)

146-148: capture_exception(e) calls in repos.py lack operation context — inconsistent with analysis.py.

In analysis.py, every capture_exception call passes operation= and repo_id= for Sentry context. Here (and in the other handlers at Lines 176, 269, 390, 480), only the bare exception is sent. This makes Sentry alerts harder to triage.

♻️ Suggested improvement (same pattern for Lines 176, 269, 390, 480)
-        capture_exception(e)
+        capture_exception(e, operation="add_repository", user_id=user_id)
-        capture_exception(e)
+        capture_exception(e, operation="delete_repository", repo_id=repo_id)
-        capture_exception(e)
+        capture_exception(e, operation="index_repository", repo_id=repo_id)
-        capture_exception(e)
+        capture_exception(e, operation="async_indexing", repo_id=repo_id)
-        capture_exception(e)
+        capture_exception(e, operation="start_async_indexing", repo_id=repo_id)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routes/repos.py` around lines 146 - 148, The capture_exception calls
in repos.py should include Sentry context like the rest of the codebase; update
each bare capture_exception(e) (the one following logger.error("Failed to add
repository", error=str(e), user_id=user_id) and the similar handlers at the
other error sites) to pass operation and repo_id (or repo_id=None when
unavailable) — e.g., capture_exception(e, operation="add_repository",
repo_id=repo_id) — and ensure the accompanying logger.error retains user_id and
error details so Sentry events match the local logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@backend/routes/playground.py`:
- Around line 488-491: In the playground error handler for the playground_search
operation, make the logging order consistent with other handlers by calling
logger.error(...) before capture_exception(...); locate the except block that
currently calls capture_exception(e, operation="playground_search") then
logger.error(...) and swap them so the error is logged first (including the
error string) and then capture_exception is invoked, leaving the HTTPException
raise unchanged.

In `@backend/routes/repos.py`:
- Around line 146-148: The capture_exception calls in repos.py should include
Sentry context like the rest of the codebase; update each bare
capture_exception(e) (the one following logger.error("Failed to add repository",
error=str(e), user_id=user_id) and the similar handlers at the other error
sites) to pass operation and repo_id (or repo_id=None when unavailable) — e.g.,
capture_exception(e, operation="add_repository", repo_id=repo_id) — and ensure
the accompanying logger.error retains user_id and error details so Sentry events
match the local logs.

In `@backend/tests/test_error_leaking.py`:
- Around line 6-7: Patch out Sentry's capture calls in these tests by mocking
sentry_sdk.capture_exception (e.g., with unittest.mock.patch or pytest
monkeypatch) inside TestErrorResponsesHideInternals (or each individual test) so
tests don't call real Sentry in CI; update the tests to assert the mock was
called with the expected exception/context and restore the original after the
test. Locate the tests in TestErrorResponsesHideInternals and wrap the
request/handler invocation with a patched capture_exception, or add a
setup/teardown that applies the patch for all three tests, then replace any
direct assertions about external effects with assertions against the mock.
- Around line 1-68: The test methods test_search_error_hides_details,
test_dependency_graph_error_hides_details, and test_repo_add_error_hides_details
are missing type hints on their parameters; add annotations (e.g., self:
"TestErrorResponsesHideInternals", client: TestClient or FlaskClient,
valid_headers: dict[str, str]) to each signature and import any needed typing
(from typing import Dict or use built-in dict[str, str]) so the file complies
with the backend/**/*.py type-hint rule.

@vercel

vercel Bot commented Feb 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
opencodeintel Ignored Ignored Preview Feb 23, 2026 0:47am

@DevanshuNEU DevanshuNEU merged commit c667760 into OpenCodeIntel:main Feb 23, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant