Skip to content

chore: error handling#6657

Merged
sriramveeraghanta merged 4 commits intopreviewfrom
fix-server-errors
Feb 24, 2025
Merged

chore: error handling#6657
sriramveeraghanta merged 4 commits intopreviewfrom
fix-server-errors

Conversation

@pablohashescobar
Copy link
Member

@pablohashescobar pablohashescobar commented Feb 21, 2025

Description

fix: server error handling

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Test Scenarios

  • ai completions
  • reset password endpoint
  • intake issue list
  • issue activity for cycle add, remove, delete and transfer
  • issue detail get endpoint using issue sequence id

Summary by CodeRabbit

  • Refactor
    • Enhanced AI response generation by transitioning to an updated language model provider for improved processing.
  • Bug Fixes
    • Strengthened the password reset flow with robust error handling to better guide users when tokens are invalid.
  • Chores
    • Upgraded the core AI dependency to the latest version for enhanced compatibility and performance.
  • New Features
    • Improved error handling when retrieving intake objects, providing clearer feedback when not found.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2025

Walkthrough

The changes update how the application interacts with its language model provider by replacing the previous litellm integration with the OpenAI library. In the external view, the API call method is modified along with changes to response extraction. Additionally, the password reset endpoint is enhanced with a nested try block for robust error handling. Other modifications include improved error handling in various components and updates to dependency versions in the requirements files.

Changes

File(s) Change Summary
apiserver/.../external/base.py, apiserver/.../base.txt Replaced litellm usage with OpenAI in the LLM response function; updated API call structure and response handling; changed dependency version from litellm==1.51.0 to openai==1.63.2.
apiserver/.../password_management.py Enhanced error handling in ResetPasswordEndpoint by adding nested try blocks to capture decoding failures and missing users, then raising a properly formatted AuthenticationException.
apiserver/.../intake/base.py Modified the list method in IntakeIssueViewSet to improve error handling for missing Intake objects, returning a 404 error when not found.
apiserver/.../issue/base.py Added strict_str_to_int method to validate and convert string to integer in IssueDetailIdentifierEndpoint, improving error handling for invalid issue identifiers.
apiserver/.../module/issue.py Updated logic in create_issue_modules to safely retrieve module_name, preventing potential AttributeError.
apiserver/.../issue_activities_task.py Introduced validation for project_id in issue_activity function to ensure it is a valid UUID, enhancing error handling.
apiserver/.../valid_uuid.py Added is_valid_uuid function to validate UUID strings, returning True or False based on validity.
apiserver/.../local.txt Updated ruff package version from 0.4.2 to 0.9.7.

Possibly related PRs

Suggested labels

🐛bug, ⚙️backend

Suggested reviewers

  • sriramveeraghanta

Poem

I'm a rabbit in the code, so fleet,
Hopping through changes, light on my feet.
New calls and errors, neatly arranged,
With each commit, the code's re-changed.
I nibble on bugs and hop past the rest,
Celebrating a build that's truly the best!
🐇🌟

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

base_host(request=request, is_app=True),
"accounts/reset-password?" + urlencode(params),
)
return HttpResponseRedirect(url)

Check warning

Code scanning / CodeQL

URL redirection from remote source Medium

Untrusted URL redirection depends on a
user-provided value
.

Copilot Autofix

AI about 1 year ago

To fix the problem, we need to ensure that the URL used in the HttpResponseRedirect function is safe and not influenced by untrusted user input. We can achieve this by validating the constructed URL before using it for redirection. Specifically, we can use the url_has_allowed_host_and_scheme function from Django to check that the URL is safe.

  1. Import the url_has_allowed_host_and_scheme function from django.utils.http.
  2. Validate the constructed URL using url_has_allowed_host_and_scheme before redirecting.
Suggested changeset 1
apiserver/plane/authentication/views/app/password_management.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/apiserver/plane/authentication/views/app/password_management.py b/apiserver/plane/authentication/views/app/password_management.py
--- a/apiserver/plane/authentication/views/app/password_management.py
+++ b/apiserver/plane/authentication/views/app/password_management.py
@@ -17,3 +17,3 @@
 from django.utils.encoding import DjangoUnicodeDecodeError, smart_bytes, smart_str
-from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
+from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode, url_has_allowed_host_and_scheme
 from django.views import View
@@ -111,7 +111,11 @@
                 params = exc.get_error_dict()
+                base_url = base_host(request=request, is_app=True)
                 url = urljoin(
-                    base_host(request=request, is_app=True),
+                    base_url,
                     "accounts/reset-password?" + urlencode(params),
                 )
-                return HttpResponseRedirect(url)
+                if url_has_allowed_host_and_scheme(url, allowed_hosts={base_url}):
+                    return HttpResponseRedirect(url)
+                else:
+                    return HttpResponseRedirect('/')
 
@@ -124,7 +128,11 @@
                 params = exc.get_error_dict()
+                base_url = base_host(request=request, is_app=True)
                 url = urljoin(
-                    base_host(request=request, is_app=True),
+                    base_url,
                     "accounts/reset-password?" + urlencode(params),
                 )
-                return HttpResponseRedirect(url)
+                if url_has_allowed_host_and_scheme(url, allowed_hosts={base_url}):
+                    return HttpResponseRedirect(url)
+                else:
+                    return HttpResponseRedirect('/')
 
@@ -137,7 +145,11 @@
                 )
+                base_url = base_host(request=request, is_app=True)
                 url = urljoin(
-                    base_host(request=request, is_app=True),
+                    base_url,
                     "accounts/reset-password?" + urlencode(exc.get_error_dict()),
                 )
-                return HttpResponseRedirect(url)
+                if url_has_allowed_host_and_scheme(url, allowed_hosts={base_url}):
+                    return HttpResponseRedirect(url)
+                else:
+                    return HttpResponseRedirect('/')
 
@@ -150,7 +162,11 @@
                 )
+                base_url = base_host(request=request, is_app=True)
                 url = urljoin(
-                    base_host(request=request, is_app=True),
+                    base_url,
                     "accounts/reset-password?" + urlencode(exc.get_error_dict()),
                 )
-                return HttpResponseRedirect(url)
+                if url_has_allowed_host_and_scheme(url, allowed_hosts={base_url}):
+                    return HttpResponseRedirect(url)
+                else:
+                    return HttpResponseRedirect('/')
 
@@ -161,7 +177,11 @@
 
+            base_url = base_host(request=request, is_app=True)
             url = urljoin(
-                base_host(request=request, is_app=True),
+                base_url,
                 "sign-in?" + urlencode({"success": True}),
             )
-            return HttpResponseRedirect(url)
+            if url_has_allowed_host_and_scheme(url, allowed_hosts={base_url}):
+                return HttpResponseRedirect(url)
+            else:
+                return HttpResponseRedirect('/')
         except DjangoUnicodeDecodeError:
@@ -171,6 +191,10 @@
             )
+            base_url = base_host(request=request, is_app=True)
             url = urljoin(
-                base_host(request=request, is_app=True),
+                base_url,
                 "accounts/reset-password?" + urlencode(exc.get_error_dict()),
             )
-            return HttpResponseRedirect(url)
+            if url_has_allowed_host_and_scheme(url, allowed_hosts={base_url}):
+                return HttpResponseRedirect(url)
+            else:
+                return HttpResponseRedirect('/')
EOF
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: 0

🧹 Nitpick comments (3)
apiserver/plane/app/views/external/base.py (2)

119-126: Add robust handling for empty or malformed response objects.

While this logic looks correct, it depends on chat_completion.choices[0].message.content being present. If the response is empty, this may raise an error. Consider checking for an empty choices list or missing fields to guard against unexpected responses.


180-180: Eliminate duplicate provider checks to adhere to DRY principles.

This repetition of if not api_key or not model or not provider: already appears at line 143. Consider extracting it into a helper function or consolidating it at a single point to improve maintainability.

apiserver/plane/authentication/views/app/password_management.py (1)

103-116: Improve readability by reducing nested try blocks.

This new nested try/except block correctly handles invalid uidb64 and missing user scenarios. However, nesting can be reduced by separating decode logic and user fetch logic into distinct exceptions. This minor refactor would improve clarity while preserving robust error handling.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fac320 and 3c2813f.

📒 Files selected for processing (3)
  • apiserver/plane/app/views/external/base.py (3 hunks)
  • apiserver/plane/authentication/views/app/password_management.py (1 hunks)
  • apiserver/requirements/base.txt (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Analyze (python)
🔇 Additional comments (4)
apiserver/plane/app/views/external/base.py (1)

6-6: Verify import feasibility and usage alignment with the official OpenAI library.

The official OpenAI Python package typically provides a module-level API via import openai. Initializing a client with OpenAI(api_key=...) might rely on a custom wrapper or an older version. Please confirm that OpenAI is indeed a valid class from your installed package.

apiserver/requirements/base.txt (3)

7-7: No notable functional impact.


69-69: No meaningful change detected.


40-40:

Details

✅ Verification successful

Check pinned version for security and compatibility.

Pinning openai==1.63.2 ensures consistent behavior but may mask available security or performance patches. Consider verifying if a broader version range is acceptable.


🏁 Script executed:

#!/bin/bash
# Description: Query PyPI for the latest version of openai and any known vulnerabilities.

curl -s https://pypi.org/pypi/openai/json | jq '.info.version'
gh api graphql -f query='
{
  securityVulnerabilities(first: 10, ecosystem: PIP, package: "openai") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
    }
  }
}
'

Length of output: 358


Verified: Pinned openai==1.63.2 is up-to-date and secure.

The PyPI query confirms that version 1.63.2 is the latest available release and no security vulnerabilities were reported. Since the pin reflects the current release, it maintains consistent and secure dependency management. If you later decide to use a broader version range for automatic updates, please ensure that compatibility and security are revisited periodically.

@pablohashescobar pablohashescobar changed the title fix: server error handling chore: error handling Feb 21, 2025
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: 0

🧹 Nitpick comments (1)
apiserver/plane/app/views/intake/base.py (1)

177-181: LGTM! Good error handling improvement.

The addition of explicit error handling for missing intake is a good practice. Consider making the error message more descriptive.

-            return Response({"error": "Intake not found"}, status=status.HTTP_404_NOT_FOUND)
+            return Response(
+                {"error": f"Intake not found for project {project_id}"}, 
+                status=status.HTTP_404_NOT_FOUND
+            )
🧰 Tools
🪛 Ruff (0.8.2)

181-181: Line too long (92 > 88)

(E501)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c2813f and beb516d.

📒 Files selected for processing (1)
  • apiserver/plane/app/views/intake/base.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
apiserver/plane/app/views/intake/base.py

181-181: Line too long (92 > 88)

(E501)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Analyze (python)
🔇 Additional comments (1)
apiserver/plane/app/views/intake/base.py (1)

187-187: LGTM! Consistent variable usage.

The change from intake_id.id to intake.id maintains consistency with the updated variable naming above.

@pablohashescobar pablohashescobar added ⚙️backend 🐛bug Something isn't working labels Feb 24, 2025
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: 0

🧹 Nitpick comments (7)
apiserver/requirements/local.txt (1)

1-1: Verify the Removal of Base Requirements Inclusion.

The -r base.txt directive has been removed, which previously included dependencies from the base requirements file. Please confirm that this change is intentional and that local requirements no longer depend on the base file. If this is part of a broader dependency management change, consider adding a comment or documentation clarifying the new structure.

apiserver/plane/utils/valid_uuid.py (1)

3-8: Consider making the UUID version optional.

The function currently enforces UUID version 4, which might be too restrictive if other UUID versions are valid in your system. Consider making the version parameter optional with version 4 as the default.

-def is_valid_uuid(uuid_str):
+def is_valid_uuid(uuid_str, version=4):
     try:
-        uuid.UUID(uuid_str, version=4)
+        uuid.UUID(uuid_str, version=version)
         return True
     except ValueError:
         return False
apiserver/plane/app/views/module/issue.py (1)

283-283: Break down the long line for better readability.

The line exceeds the recommended length limit of 88 characters. Consider breaking it down into multiple lines.

-                    {"module_name": module_issue.first().module.name if (module_issue.first() and module_issue.first().module) else None}
+                    {
+                        "module_name": (
+                            module_issue.first().module.name
+                            if (module_issue.first() and module_issue.first().module)
+                            else None
+                        )
+                    }
🧰 Tools
🪛 Ruff (0.8.2)

283-283: Line too long (137 > 88)

(E501)

apiserver/plane/app/views/issue/base.py (2)

1119-1122: Consider moving validation to a utility module.

The strict_str_to_int method could be moved to a utility module since it's a generic validation function that might be useful elsewhere in the codebase.

Consider creating a new utility module like plane/utils/validators.py and moving this function there.


1126-1133: Improve error message for invalid issue identifier.

The error message could be more descriptive to help users understand what constitutes a valid issue identifier.

-                {"error": "Invalid issue identifier"},
+                {
+                    "error": "Invalid issue identifier. Expected a numeric value.",
+                    "hint": "Issue identifiers must be positive or negative integers."
+                },
apiserver/plane/bgtasks/issue_activities_task.py (2)

1571-1573: Log invalid project_id values.

The early return on invalid UUID should log the error to help with debugging.

         # check if project_id is valid
         if not is_valid_uuid(project_id):
+            log_exception(f"Invalid project_id UUID format: {project_id}")
             return

1568-1574: Move UUID validation before try block.

The UUID validation should be performed before entering the try block since it's a precondition check.

+    # check if project_id is valid
+    if not is_valid_uuid(project_id):
+        log_exception(f"Invalid project_id UUID format: {project_id}")
+        return
+
     try:
         issue_activities = []
-
-        # check if project_id is valid
-        if not is_valid_uuid(project_id):
-            return
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between beb516d and cc50639.

📒 Files selected for processing (5)
  • apiserver/plane/app/views/issue/base.py (3 hunks)
  • apiserver/plane/app/views/module/issue.py (1 hunks)
  • apiserver/plane/bgtasks/issue_activities_task.py (3 hunks)
  • apiserver/plane/utils/valid_uuid.py (1 hunks)
  • apiserver/requirements/local.txt (1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
apiserver/plane/app/views/module/issue.py

283-283: Line too long (137 > 88)

(E501)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Analyze (python)
🔇 Additional comments (1)
apiserver/requirements/local.txt (1)

5-5: Confirm Updated Ruff Version Compatibility.

The version of ruff has been updated from 0.4.2 to 0.9.7. Please verify that this upgrade is compatible with the project's linting configuration and does not introduce new linting rules or issues that might affect production code. It might be useful to run linting tests post-upgrade to be sure.

@sriramveeraghanta sriramveeraghanta merged commit da469da into preview Feb 24, 2025
5 of 6 checks passed
@sriramveeraghanta sriramveeraghanta deleted the fix-server-errors branch February 24, 2025 08:06
lifeiscontent pushed a commit that referenced this pull request Aug 18, 2025
* fix: ai completions

* fix: reset password endpoints

* fix: intake issue list

* fix: identifier validation, uuid validation
@andreyrd
Copy link

Maybe I'm confused, but didn't this break support for Anthropic/Gemini as LLM providers??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚙️backend 🐛bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants