Skip to content

fix(proxy): treat all PrismaError subclasses as db connection errors - #21773

Closed
ishaan-jaff wants to merge 2 commits into
mainfrom
fix/prisma-db-connection-error-classification
Closed

fix(proxy): treat all PrismaError subclasses as db connection errors#21773
ishaan-jaff wants to merge 2 commits into
mainfrom
fix/prisma-db-connection-error-classification

Conversation

@ishaan-jaff

Copy link
Copy Markdown
Contributor

Relevant issues

Regression introduced in #21706 (commit e012971, "fix(proxy): narrow prisma db connection error classification").

Pre-Submission checklist

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

Type

🐛 Bug Fix

Changes

is_database_connection_error was narrowed in #21706 to only match PrismaError when its message contained specific connectivity keywords ("connection refused", "timed out", etc.). But allow_requests_on_db_unavailable=True is supposed to let requests through on ANY prisma DB error — not just network-level ones.

Reverts the keyword guard so that any prisma.errors.PrismaError subclass is treated as a DB error, restoring the behavior before the regression.

Tests fixed by this change:

  • test_delete_access_group_503_on_db_connection_error — delete endpoint was returning 500 instead of 503 when PrismaError was raised in a transaction
  • test_handle_authentication_error_db_unavailable[prisma_error0] — bare PrismaError()
  • test_handle_authentication_error_db_unavailable[prisma_error1]DataError
  • test_handle_authentication_error_db_unavailable[prisma_error2]UniqueViolationError
  • test_handle_authentication_error_db_unavailable[prisma_error3]ForeignKeyViolationError
  • test_handle_authentication_error_db_unavailable[prisma_error4]MissingRequiredValueError
  • test_handle_authentication_error_db_unavailable[prisma_error5]RawQueryError
  • test_handle_authentication_error_db_unavailable[prisma_error6]TableNotFoundError
  • test_handle_authentication_error_db_unavailable[prisma_error7]RecordNotFoundError

… pubsub fixture

Bedrock KB tests were hitting the anthropic API (via berrie proxy) and getting
401s. Fixed by mocking the AsyncHTTPHandler.post call in the 4 failing tests.

GCS pubsub v1 test was failing because SpendLogsMetadata added new fields
(user_api_key, status, error_information, etc.) that weren't in the expected
spend_logs_payload.json fixture.
@vercel

vercel Bot commented Feb 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Feb 21, 2026 6:19pm

Request Review

@greptile-apps

greptile-apps Bot commented Feb 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Reverts the keyword-based narrowing of is_database_connection_error introduced in #21706, restoring the original behavior where any prisma.errors.PrismaError subclass is treated as a database error. This fixes the regression where allow_requests_on_db_unavailable=True stopped allowing requests through on non-network Prisma errors. Also mocks HTTP calls in bedrock knowledge base tests and updates a GCS pub/sub test fixture.

  • Regression fix: is_database_connection_error now returns True for all PrismaError subclasses, restoring the allow_requests_on_db_unavailable behavior.
  • Missing test update: The existing unit test test_is_database_connection_error_non_connection_prisma_errors in tests/test_litellm/proxy/db/test_exception_handler.py was not updated and will now fail — it asserts False for errors that now return True.
  • Over-classification risk: Other call sites (delete_access_group, DB health watchdog, auth key lookup) use is_database_connection_error for different purposes (503 responses, reconnection). Broadening it means non-connection errors like RecordNotFoundError could incorrectly trigger 503 responses or unnecessary DB reconnect attempts.
  • Test improvement: Bedrock knowledge base tests now mock Anthropic HTTP calls instead of making live requests.

Confidence Score: 2/5

  • This PR fixes one regression but introduces test failures and potential misclassification of non-connection Prisma errors at other call sites.
  • The core logic change is reasonable for the allow_requests_on_db_unavailable use case, but the existing unit test test_is_database_connection_error_non_connection_prisma_errors will definitely fail since it was not updated. Additionally, broadening is_database_connection_error affects multiple call sites beyond the intended fix — the delete endpoint will return 503 for non-connection errors, and the DB watchdog/auth checks will trigger unnecessary reconnects.
  • Pay close attention to litellm/proxy/db/exception_handler.py — the broadened is_database_connection_error breaks existing tests and has unintended side effects in access_group_endpoints.py, proxy/utils.py, and auth/auth_checks.py.

Important Files Changed

Filename Overview
litellm/proxy/db/exception_handler.py Broadens is_database_connection_error to treat ALL PrismaError subclasses as DB connection errors. Reverts regression from #21706 but introduces over-classification — existing unit tests not updated and non-connection callers will misclassify errors.
tests/logging_callback_tests/gcs_pub_sub_body/spend_logs_payload.json Test fixture updated to include additional metadata fields in the spend logs payload JSON. No functional concerns.
tests/logging_callback_tests/test_bedrock_knowledgebase_hook.py Replaces live Anthropic HTTP calls with mocked responses in bedrock knowledge base tests. Good improvement — tests no longer depend on external API availability.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Exception raised] --> B{isinstance PrismaError?}
    B -->|Yes - NEW behavior| C[Return True: DB connection error]
    B -->|No| D{isinstance DB_CONNECTION_ERROR_TYPES?}
    D -->|Yes| C
    D -->|No| E{isinstance ClientNotConnected / HTTPClientClosed?}
    E -->|Yes| C
    E -->|No| F{ProxyException with no_db_connection?}
    F -->|Yes| C
    F -->|No| G[Return False: not a DB error]

    C --> H{Call site context}
    H -->|handle_db_exception| I[allow_requests_on_db_unavailable check]
    H -->|delete_access_group| J["Returns 503 ⚠️ even for RecordNotFoundError"]
    H -->|DB health watchdog| K["Triggers reconnect ⚠️ even for non-connection errors"]
    H -->|auth_checks| L["Triggers reconnect ⚠️ even for data errors"]
Loading

Last reviewed commit: 54e9d1f

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 45 to +46
if isinstance(e, prisma.errors.PrismaError):
error_message = str(e).lower()
# Treat generic PrismaError as connection error only when its text
# clearly indicates transport/connectivity failure.
connection_keywords = (
"can't reach database server",
"cannot reach database server",
"can't connect",
"cannot connect",
"connection error",
"connection closed",
"timed out",
"timeout",
"connection refused",
"network is unreachable",
"no route to host",
"broken pipe",
)
if any(keyword in error_message for keyword in connection_keywords):
return True
return True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Existing unit test will fail

The test test_is_database_connection_error_non_connection_prisma_errors in tests/test_litellm/proxy/db/test_exception_handler.py:75-76 asserts that PrismaError(), DataError, UniqueViolationError, ForeignKeyViolationError, MissingRequiredValueError, RawQueryError, TableNotFoundError, and RecordNotFoundError all return False from is_database_connection_error. With this change, all of them will return True, causing 8 test failures.

This test file was not updated as part of this PR. It needs to be updated to match the new intended behavior (either by asserting True for those cases, or removing those test cases).

Context Used: Rule from dashboard - What: Ensure that any PR claiming to fix an issue includes evidence that the issue is resolved, such... (source)

Comment on lines 45 to +46
if isinstance(e, prisma.errors.PrismaError):
error_message = str(e).lower()
# Treat generic PrismaError as connection error only when its text
# clearly indicates transport/connectivity failure.
connection_keywords = (
"can't reach database server",
"cannot reach database server",
"can't connect",
"cannot connect",
"connection error",
"connection closed",
"timed out",
"timeout",
"connection refused",
"network is unreachable",
"no route to host",
"broken pipe",
)
if any(keyword in error_message for keyword in connection_keywords):
return True
return True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-connection errors misclassified as connection errors

This broadening causes unintended side effects in call sites that use is_database_connection_error for purposes other than allow_requests_on_db_unavailable:

  1. access_group_endpoints.py:333: A RecordNotFoundError during delete_access_group will now match is_database_connection_error and return 503 Service Unavailable instead of falling through to the P2025/not-found check on line 338, which would correctly return 404.

  2. proxy/utils.py:4113: The DB health watchdog uses is_database_connection_error to decide whether to trigger a reconnect. With this change, any PrismaError (e.g. a query syntax error or unique violation from the SELECT 1 probe — unlikely but possible in edge cases) would trigger unnecessary reconnection attempts.

  3. auth/auth_checks.py:2003: Same pattern — a UniqueViolationError or DataError during key lookup would trigger a DB reconnect attempt when no connectivity issue actually exists.

Consider either:

  • Keeping the broad match only for the handle_db_exception / allow_requests_on_db_unavailable path (separate method), or
  • At minimum, reordering the check in access_group_endpoints.py so the P2025 check runs before is_database_connection_error.

@ishaan-jaff

Copy link
Copy Markdown
Contributor Author

Superseded by #21778 — wrong approach (broadened production code instead of fixing the tests)

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