Skip to content

Conversation

@Vasilije1990
Copy link
Contributor

@Vasilije1990 Vasilije1990 commented Dec 28, 2025

Description

Acceptance Criteria

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Other (please specify):

Screenshots/Videos (if applicable)

Pre-submission Checklist

  • I have tested my changes thoroughly before submitting this PR
  • This PR contains minimal changes necessary to address the issue/feature
  • My code follows the project's coding standards and style guidelines
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if applicable)
  • All new and existing tests pass
  • I have searched existing PRs to ensure this change hasn't been submitted already
  • I have linked any relevant issues in the description
  • My commits have clear and descriptive messages

DCO Affirmation

I affirm that all code in every commit of this pull request conforms to the terms of the Topoteretes Developer Certificate of Origin.

Summary by CodeRabbit

  • Bug Fixes
    • Improved error messaging in search functionality with clearer, actionable feedback when database or user configuration prerequisites are not met
    • Standardized error response format for consistent and informative error reporting across search operations

✏️ Tip: You can customize this high-level summary in your review settings.

@cursor
Copy link

cursor bot commented Dec 28, 2025

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on January 6.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@pull-checklist
Copy link

Please make sure all the checkboxes are checked:

  • I have tested these changes locally.
  • I have reviewed the code changes.
  • I have added end-to-end and unit tests (if applicable).
  • I have updated the documentation and README.md file (if necessary).
  • I have removed unnecessary code and debug statements.
  • PR title is clear and follows the convention.
  • I have tagged reviewers or team members for feedback.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 28, 2025

Walkthrough

Two search-related modules add error handling to catch database and user-related exceptions (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) during search initialization. These exceptions are now converted to structured 422 validation responses instead of propagating raw stacktraces.

Changes

Cohort / File(s) Summary
Search error handling
cognee/api/v1/search/routers/get_search_router.py, cognee/api/v1/search/search.py
Added imports for DatabaseNotCreatedError, UserNotFoundError, and CogneeValidationError. In the router, extended exception handling to catch and return 422 JSONResponse with structured error payload for these exceptions. In the search module, wrapped get_default_user() call with try/except to catch database and user errors, then raise CogneeValidationError with explicit precondition message instead of propagating low-level exceptions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is entirely template-based with no manual content filled in, lacking human-provided context about the changes, reasoning, acceptance criteria, and testing details. Provide a clear human-generated description of the changes, acceptance criteria, type of change selection, and verification instructions instead of submitting the empty template.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: improving error messages when cognee is run without prior setup (cognee.add/cognee.cognify).
Linked Issues check ✅ Passed The code changes implement better error handling that catches DatabaseNotCreatedError, UserNotFoundError, and CogneeValidationError, returning a 422 response with structured error messages instead of exposing internal stacktraces, directly addressing the issue's requirement for more informative error messages.
Out of Scope Changes check ✅ Passed All changes are focused on improving error messages and handling for the search flow when the database hasn't been initialized, staying within the scope of issue COG-3283.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch COG-3283

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

Comment on lines +148 to +152
content={
"error": "Search prerequisites not met",
"detail": str(e),
"hint": "Run `await cognee.add(...)` then `await cognee.cognify()` before searching.",
},

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 10 days ago

In general, to fix this class of problem, the API should never send raw exception messages or stack traces back to the client. Instead, it should (a) log the full exception (with traceback) on the server for debugging/monitoring, and (b) return a generic, user-safe error message or a carefully curated, non-sensitive message. Custom exceptions that are intended for client consumption should provide a sanitized, structured payload rather than relying on str(e).

For this specific code, we can keep the behavior and HTTP status codes but stop exposing raw exception messages. The best minimal fix is:

  1. Add a logger for this module (using Python’s standard logging library).
  2. In the except (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) as e: block:
    • Log the exception with traceback.
    • Return a JSON response whose detail is a generic, non-sensitive message (for example, based on the exception class name) rather than str(e).
  3. In the except Exception as error: block:
    • Log the exception with traceback.
    • Return a generic 409 response like {"error": "Search operation failed"} and omit str(error).

This preserves:

  • Distinct handling and status codes for known precondition/validation errors vs generic server-side errors.
  • The hint text that is already generic and safe.
  • The PermissionDeniedError behavior (empty list) unchanged.

Concretely, in cognee/api/v1/search/routers/get_search_router.py:

  • Add import logging at the top and define logger = logging.getLogger(__name__).
  • Modify the first exception handler to:
    • Call logger.exception("Search prerequisites not met").
    • Replace "detail": str(e) with a generic message, for instance using e.__class__.__name__ or a static text.
  • Modify the generic exception handler to:
    • Call logger.exception("Unexpected error during search").
    • Replace {"error": str(error)} with a generic error message.

No new external dependencies are required; we use Python’s built-in logging only.


Suggested changeset 1
cognee/api/v1/search/routers/get_search_router.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/cognee/api/v1/search/routers/get_search_router.py b/cognee/api/v1/search/routers/get_search_router.py
--- a/cognee/api/v1/search/routers/get_search_router.py
+++ b/cognee/api/v1/search/routers/get_search_router.py
@@ -5,6 +5,7 @@
 from fastapi import Depends, APIRouter
 from fastapi.responses import JSONResponse
 from fastapi.encoders import jsonable_encoder
+import logging
 
 from cognee.modules.search.types import SearchType, SearchResult, CombinedSearchResult
 from cognee.api.DTO import InDTO, OutDTO
@@ -17,7 +18,9 @@
 from cognee.infrastructure.databases.exceptions import DatabaseNotCreatedError
 from cognee.exceptions import CogneeValidationError
 
+logger = logging.getLogger(__name__)
 
+
 # Note: Datasets sent by name will only map to datasets owned by the request sender
 #       To search for datasets not owned by the request sender dataset UUID is needed
 class SearchPayloadDTO(InDTO):
@@ -142,18 +144,23 @@
             return jsonable_encoder(results)
         except (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) as e:
             # Return a clear 422 with actionable guidance instead of leaking a stacktrace
+            logger.exception("Search prerequisites not met")
             status_code = getattr(e, "status_code", 422)
             return JSONResponse(
                 status_code=status_code,
                 content={
                     "error": "Search prerequisites not met",
-                    "detail": str(e),
+                    "detail": "One or more search prerequisites or validations failed.",
                     "hint": "Run `await cognee.add(...)` then `await cognee.cognify()` before searching.",
                 },
             )
         except PermissionDeniedError:
             return []
         except Exception as error:
-            return JSONResponse(status_code=409, content={"error": str(error)})
+            logger.exception("Unexpected error during search")
+            return JSONResponse(
+                status_code=409,
+                content={"error": "Search operation failed due to an internal error."},
+            )
 
     return router
EOF
@@ -5,6 +5,7 @@
from fastapi import Depends, APIRouter
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
import logging

from cognee.modules.search.types import SearchType, SearchResult, CombinedSearchResult
from cognee.api.DTO import InDTO, OutDTO
@@ -17,7 +18,9 @@
from cognee.infrastructure.databases.exceptions import DatabaseNotCreatedError
from cognee.exceptions import CogneeValidationError

logger = logging.getLogger(__name__)


# Note: Datasets sent by name will only map to datasets owned by the request sender
# To search for datasets not owned by the request sender dataset UUID is needed
class SearchPayloadDTO(InDTO):
@@ -142,18 +144,23 @@
return jsonable_encoder(results)
except (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) as e:
# Return a clear 422 with actionable guidance instead of leaking a stacktrace
logger.exception("Search prerequisites not met")
status_code = getattr(e, "status_code", 422)
return JSONResponse(
status_code=status_code,
content={
"error": "Search prerequisites not met",
"detail": str(e),
"detail": "One or more search prerequisites or validations failed.",
"hint": "Run `await cognee.add(...)` then `await cognee.cognify()` before searching.",
},
)
except PermissionDeniedError:
return []
except Exception as error:
return JSONResponse(status_code=409, content={"error": str(error)})
logger.exception("Unexpected error during search")
return JSONResponse(
status_code=409,
content={"error": "Search operation failed due to an internal error."},
)

return router
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
cognee/api/v1/search/routers/get_search_router.py (2)

143-143: Consider narrowing the exception catch to avoid unrelated validation errors.

Catching CogneeValidationError broadly at the router level could inadvertently handle unrelated validation errors from deeper in the search pipeline (e.g., query validation, parameter validation) that might need different treatment or HTTP status codes.

Since search.py now raises a specifically named CogneeValidationError with name="SearchPreconditionError", you could check the exception's name attribute to distinguish precondition failures from other validation errors.

🔎 Optional: filter by exception name
-        except CogneeValidationError as e:
+        except CogneeValidationError as e:
+            # Only handle precondition errors here; let others propagate
+            if getattr(e, "name", None) != "SearchPreconditionError":
+                raise
             # Return a clear 422 with actionable guidance instead of leaking a stacktrace
             status_code = getattr(e, "status_code", 422)

This ensures only the specific precondition check is handled here, while other validation errors fall through to the general Exception handler or propagate appropriately.


148-152: Add a comment explaining that str(e) is safe for external users.

The caught exceptions (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) all define safe, user-friendly default messages and inherit a __str__ method that returns only the exception name, message, and status code—no stack traces. However, add a brief comment at line 150 documenting this assumption (e.g., "Safe to expose: CogneeApiError subclasses have user-facing messages") to clarify for future maintainers why using str(e) in the response is acceptable here.

cognee/api/v1/search/search.py (1)

186-191: Consider simpler formatting for JSON-serialized error messages.

The message uses newline characters (\n) and bullet points () which may not render well when serialized to JSON and displayed in API clients, terminals, or log aggregators. A single-line message or one using simple punctuation would be more portable.

🔎 Suggested simplification
             raise CogneeValidationError(
                 message=(
-                    "Search prerequisites not met: no database/default user found. "
-                    "Initialize Cognee before searching by:\n"
-                    "• running `await cognee.add(...)` followed by `await cognee.cognify()`."
+                    "Search prerequisites not met: no database or default user found. "
+                    "Initialize Cognee before searching by running "
+                    "`await cognee.add(...)` followed by `await cognee.cognify()`."
                 ),
                 name="SearchPreconditionError",
             ) from error

This preserves clarity while ensuring the message displays consistently across different interfaces.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 310e9e9 and ce68555.

📒 Files selected for processing (2)
  • cognee/api/v1/search/routers/get_search_router.py
  • cognee/api/v1/search/search.py
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use 4-space indentation in Python code
Use snake_case for Python module and function names
Use PascalCase for Python class names
Use ruff format before committing Python code
Use ruff check for import hygiene and style enforcement with line-length 100 configured in pyproject.toml
Prefer explicit, structured error handling in Python code

Files:

  • cognee/api/v1/search/search.py
  • cognee/api/v1/search/routers/get_search_router.py

⚙️ CodeRabbit configuration file

**/*.py: When reviewing Python code for this project:

  1. Prioritize portability over clarity, especially when dealing with cross-Python compatibility. However, with the priority in mind, do still consider improvements to clarity when relevant.
  2. As a general guideline, consider the code style advocated in the PEP 8 standard (excluding the use of spaces for indentation) and evaluate suggested changes for code style compliance.
  3. As a style convention, consider the code style advocated in CEP-8 and evaluate suggested changes for code style compliance.
  4. As a general guideline, try to provide any relevant, official, and supporting documentation links to any tool's suggestions in review comments. This guideline is important for posterity.
  5. As a general rule, undocumented function definitions and class definitions in the project's Python code are assumed incomplete. Please consider suggesting a short summary of the code for any of these incomplete definitions as docstrings when reviewing.

Files:

  • cognee/api/v1/search/search.py
  • cognee/api/v1/search/routers/get_search_router.py
cognee/api/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Public APIs should be type-annotated in Python where practical

Files:

  • cognee/api/v1/search/search.py
  • cognee/api/v1/search/routers/get_search_router.py
cognee/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Use shared logging utilities from cognee.shared.logging_utils in Python code

Files:

  • cognee/api/v1/search/search.py
  • cognee/api/v1/search/routers/get_search_router.py
🧬 Code graph analysis (2)
cognee/api/v1/search/search.py (4)
cognee/infrastructure/databases/exceptions/exceptions.py (1)
  • DatabaseNotCreatedError (5-20)
cognee/exceptions/exceptions.py (1)
  • CogneeValidationError (52-63)
cognee/modules/users/exceptions/exceptions.py (1)
  • UserNotFoundError (29-38)
cognee/modules/users/methods/get_default_user.py (1)
  • get_default_user (13-38)
cognee/api/v1/search/routers/get_search_router.py (3)
cognee/modules/users/exceptions/exceptions.py (2)
  • PermissionDeniedError (41-48)
  • UserNotFoundError (29-38)
cognee/infrastructure/databases/exceptions/exceptions.py (1)
  • DatabaseNotCreatedError (5-20)
cognee/exceptions/exceptions.py (1)
  • CogneeValidationError (52-63)
🪛 GitHub Check: CodeQL
cognee/api/v1/search/routers/get_search_router.py

[warning] 148-152: Information exposure through an exception
Stack trace information flows to this location and may be exposed to an external user.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (23)
  • GitHub Check: Basic Tests / Run Integration Tests
  • GitHub Check: End-to-End Tests / Test Cognify - Edge Centered Payload
  • GitHub Check: End-to-End Tests / Test dataset database handlers in Cognee
  • GitHub Check: End-to-End Tests / Test Entity Extraction
  • GitHub Check: End-to-End Tests / Test adding of label for data in Cognee
  • GitHub Check: End-to-End Tests / Test Feedback Enrichment
  • GitHub Check: End-to-End Tests / S3 Bucket Test
  • GitHub Check: End-to-End Tests / Test permissions with different situations in Cognee
  • GitHub Check: End-to-End Tests / Concurrent Subprocess access test
  • GitHub Check: End-to-End Tests / Test graph edge ingestion
  • GitHub Check: End-to-End Tests / Test multi tenancy with different situations in Cognee
  • GitHub Check: End-to-End Tests / Conversation sessions test (Redis)
  • GitHub Check: End-to-End Tests / Conversation sessions test (FS)
  • GitHub Check: End-to-End Tests / Test using different async databases in parallel in Cognee
  • GitHub Check: Basic Tests / Run Unit Tests
  • GitHub Check: End-to-End Tests / Test dataset database deletion in Cognee
  • GitHub Check: End-to-End Tests / Deduplication Test
  • GitHub Check: End-to-End Tests / Run Telemetry Pipeline Test
  • GitHub Check: End-to-End Tests / Server Start Test
  • GitHub Check: Basic Tests / Run Simple Examples
  • GitHub Check: Basic Tests / Run Simple Examples BAML
  • GitHub Check: CLI Tests / CLI Functionality Tests
  • GitHub Check: CLI Tests / CLI Integration Tests
🔇 Additional comments (1)
cognee/api/v1/search/search.py (1)

182-193: Excellent precondition check with clear error messaging.

The try/except block correctly catches low-level exceptions (DatabaseNotCreatedError, UserNotFoundError) from get_default_user() and converts them into a user-friendly CogneeValidationError with actionable guidance. Using from error preserves the exception chain for debugging, and the custom name="SearchPreconditionError" allows downstream code to distinguish this failure mode.

Comment on lines +143 to +153
except (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) as e:
# Return a clear 422 with actionable guidance instead of leaking a stacktrace
status_code = getattr(e, "status_code", 422)
return JSONResponse(
status_code=status_code,
content={
"error": "Search prerequisites not met",
"detail": str(e),
"hint": "Run `await cognee.add(...)` then `await cognee.cognify()` before searching.",
},
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Status code semantic mismatch for UserNotFoundError.

UserNotFoundError has status_code=404 (from the exception definition), but the error response says "Search prerequisites not met" which semantically aligns with 422 (unprocessable entity), not 404 (not found). This could confuse API consumers who rely on HTTP status semantics.

Since search.py already converts both DatabaseNotCreatedError and UserNotFoundError into CogneeValidationError (which defaults to 422), consider catching only CogneeValidationError here and removing the individual exception types from the tuple to avoid this inconsistency.

🔎 Proposed fix: catch only CogneeValidationError
-        except (DatabaseNotCreatedError, UserNotFoundError, CogneeValidationError) as e:
+        except CogneeValidationError as e:
             # Return a clear 422 with actionable guidance instead of leaking a stacktrace
             status_code = getattr(e, "status_code", 422)

This simplifies the handler and ensures consistent 422 responses since search.py already normalizes the exceptions.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: CodeQL

[warning] 148-152: Information exposure through an exception
Stack trace information flows to this location and may be exposed to an external user.

🤖 Prompt for AI Agents
In cognee/api/v1/search/routers/get_search_router.py around lines 143 to 153,
the except block currently catches (DatabaseNotCreatedError, UserNotFoundError,
CogneeValidationError) causing a semantic mismatch when UserNotFoundError (404)
is returned while the body implies a 422; change the handler to catch only
CogneeValidationError (i.e., except CogneeValidationError as e) so responses are
consistently treated as validation/prerequisite errors and keep the existing
JSONResponse construction (using getattr(e, "status_code", 422) if needed).

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.

3 participants