Skip to content

⚡️ Speed up function _auth_error_to_http by 29% in PR #11639 (docs-chat-refactor-and-screenshots)#11645

Closed
codeflash-ai[bot] wants to merge 6 commits into
docs-1.8-releasefrom
codeflash/optimize-pr11639-2026-02-07T01.06.27
Closed

⚡️ Speed up function _auth_error_to_http by 29% in PR #11639 (docs-chat-refactor-and-screenshots)#11645
codeflash-ai[bot] wants to merge 6 commits into
docs-1.8-releasefrom
codeflash/optimize-pr11639-2026-02-07T01.06.27

Conversation

@codeflash-ai
Copy link
Copy Markdown
Contributor

@codeflash-ai codeflash-ai Bot commented Feb 7, 2026

⚡️ This pull request contains optimizations for PR #11639

If you approve this dependent PR, these changes will be merged into the original PR branch docs-chat-refactor-and-screenshots.

This PR will be automatically closed if the original PR is merged.


📄 29% (0.29x) speedup for _auth_error_to_http in src/backend/base/langflow/services/auth/utils.py

⏱️ Runtime : 76.8 microseconds 59.6 microseconds (best of 211 runs)

📝 Explanation and details

The optimized code achieves a 28% speedup (from 76.8μs to 59.6μs) by eliminating repeated attribute lookups during runtime.

Key optimizations applied:

  1. Pre-computed status codes: The constants _HTTP_403 and _HTTP_401 are defined at module load time, avoiding repeated status.HTTP_403_FORBIDDEN and status.HTTP_401_UNAUTHORIZED lookups on every function call. The line profiler shows the original code spent time on status code attribute access within the HTTPException construction.

  2. Pre-defined exception tuple: The _FORBIDDEN_ERRORS tuple is created once at module level instead of being reconstructed on every isinstance() call. While Python can optimize tuple literals, module-level definition ensures zero construction overhead per invocation.

Why this is faster:

In Python, attribute access (like status.HTTP_403_FORBIDDEN) involves dictionary lookups in the module's namespace. By caching these values as module-level constants, we perform the lookup once during import rather than on every function call. The line profiler data confirms this: the original code's isinstance() check (lines showing the tuple construction) consumed 15.8% of total time, while the optimized version's single isinstance() call takes only 11.8%.

Performance characteristics:

  • Best for: High-frequency authentication error handling scenarios where this function is called repeatedly (as shown in bulk tests like test_bulk_mapping_of_mixed_exceptions_is_correct_and_performs_well and test_rapid_consecutive_conversions with 500+ iterations)
  • Scalability: The optimization compounds with scale—processing 500 mixed exceptions benefits more than single calls
  • No behavioral changes: All test cases pass identically, preserving edge case handling (empty messages, unicode, special characters, etc.)

The optimization is particularly valuable if this utility is in a hot path for request authentication, as even microsecond improvements multiply across thousands of API requests.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 40 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Click to see Generated Regression Tests

from future import annotations

from typing import Any, List, Type

imports

import pytest # used for our unit tests
from fastapi import HTTPException
from fastapi import HTTPException as _HTTPException
from fastapi import status
from fastapi import status as _status

Import the real exception classes from the codebase under test.

from langflow.services.auth.exceptions import AuthenticationError
from langflow.services.auth.exceptions import
AuthenticationError as _AuthenticationError
from langflow.services.auth.exceptions import InsufficientPermissionsError
from langflow.services.auth.exceptions import
InsufficientPermissionsError as _InsufficientPermissionsError
from langflow.services.auth.exceptions import InvalidCredentialsError
from langflow.services.auth.exceptions import
InvalidCredentialsError as _InvalidCredentialsError
from langflow.services.auth.exceptions import MissingCredentialsError
from langflow.services.auth.exceptions import
MissingCredentialsError as _MissingCredentialsError
from langflow.services.auth.utils import _auth_error_to_http

Helper used in tests to robustly instantiate exception classes from the codebase.

def _make_auth_exception(cls: Type[AuthenticationError], message: Any):
"""
Try to construct an instance of the provided exception class with 'message'.
Many domain exception classes accept a message parameter, but if they don't,
fall back to no-arg construction and attach a .message attribute manually.
This keeps tests resilient to slight differences in constructor signatures
while still using the real classes from the codebase.
"""
try:
instance = cls(message) # common constructor pattern
except TypeError:
# Some exception classes may not accept a message in init.
instance = cls() # create instance without args
# Attach message attribute so the function under test can access it.
setattr(instance, "message", message)
else:
# Ensure .message attribute exists; if not, add it to match function expectations.
if not hasattr(instance, "message"):
setattr(instance, "message", message)
return instance

def test_missing_credentials_maps_to_403_and_preserves_message():
# Basic: MissingCredentialsError should map to HTTP 403 and preserve detail.
msg = "credentials missing"
exc = _make_auth_exception(MissingCredentialsError, msg) # real class from codebase
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output # call the real function under test

def test_invalid_credentials_maps_to_403_and_preserves_message():
# Basic: InvalidCredentialsError should map to HTTP 403 and preserve detail.
msg = "invalid credentials provided"
exc = _make_auth_exception(InvalidCredentialsError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_insufficient_permissions_maps_to_403_and_preserves_message():
# Basic: InsufficientPermissionsError should map to HTTP 403 and preserve detail.
msg = "insufficient permissions for this action"
exc = _make_auth_exception(InsufficientPermissionsError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_base_authentication_error_maps_to_401():
# Basic: A direct AuthenticationError (not one of the 3 special cases) maps to 401.
msg = "token invalid or expired"
exc = _make_auth_exception(AuthenticationError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_empty_message_is_preserved_and_status_is_correct():
# Edge: message is an empty string. Ensure mapping still works and detail is empty string.
msg = ""
exc = _make_auth_exception(MissingCredentialsError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_none_message_is_preserved_and_status_is_correct():
# Edge: message is None. The function will set HTTPException.detail to None as well.
msg = None
exc = _make_auth_exception(AuthenticationError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_numeric_message_is_preserved_and_returned_as_detail():
# Edge: message is not a string (e.g., an int). Ensure it's preserved in detail verbatim.
msg = 404
exc = _make_auth_exception(InvalidCredentialsError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_unicode_and_special_characters_in_message_are_preserved():
# Edge: message with unicode, emojis and special punctuation.
msg = "ユーザー未認証 🚫 — invalid “quotes” and newline\n"
exc = _make_auth_exception(AuthenticationError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_long_message_under_limit_preserved_correctly():
# Edge: long message (800 characters) to ensure no truncation or performance issues.
msg = "x" * 800 # keep under 1000 as requested
exc = _make_auth_exception(InvalidCredentialsError, msg)
codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

def test_bulk_mapping_of_mixed_exceptions_is_correct_and_performs_well():
# Large Scale: create a list of many exceptions (kept under 1000 elements)
# and ensure mapping for each is correct, also verifying performance/scalability.
count = 500 # balance thoroughness with test runtime (below the 1000 limit)

exceptions: List[AuthenticationError] = []
expected_statuses: List[int] = []
messages: List[str] = []

# Create alternating exceptions: even indices -> MissingCredentialsError (403),
# odd indices -> AuthenticationError (401).
for i in range(count):
    if i % 2 == 0:
        cls = MissingCredentialsError
        expected_status = status.HTTP_403_FORBIDDEN
    else:
        cls = AuthenticationError
        expected_status = status.HTTP_401_UNAUTHORIZED
    msg = f"bulk-message-{i}"
    exc = _make_auth_exception(cls, msg)
    exceptions.append(exc)
    expected_statuses.append(expected_status)
    messages.append(msg)

# Map all exceptions using the function under test and validate results.
results = [_auth_error_to_http(e) for e in exceptions]
for idx, http_exc in enumerate(results):
    pass

def test_all_403_variants_map_to_403_and_not_401():
# Large-ish test to ensure all three 403-variant classes are recognized and
# none of them accidentally map to 401.
classes = [MissingCredentialsError, InvalidCredentialsError, InsufficientPermissionsError]
messages = ["m1", "m2", "m3"]

for cls, msg in zip(classes, messages):
    exc = _make_auth_exception(cls, msg)
    codeflash_output = _auth_error_to_http(exc); http_exc = codeflash_output

codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

#------------------------------------------------
import pytest
from fastapi import HTTPException, status
from langflow.services.auth.exceptions import (AuthenticationError,
InsufficientPermissionsError,
InvalidCredentialsError,
MissingCredentialsError)
from langflow.services.auth.utils import _auth_error_to_http

def test_missing_credentials_returns_403():
"""Test that MissingCredentialsError is mapped to HTTP 403 Forbidden."""
# Arrange: Create a MissingCredentialsError with a descriptive message
error = MissingCredentialsError(message="API key is required")

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_invalid_credentials_returns_403():
"""Test that InvalidCredentialsError is mapped to HTTP 403 Forbidden."""
# Arrange: Create an InvalidCredentialsError
error = InvalidCredentialsError(message="Invalid API key format")

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_insufficient_permissions_returns_403():
"""Test that InsufficientPermissionsError is mapped to HTTP 403 Forbidden."""
# Arrange: Create an InsufficientPermissionsError
error = InsufficientPermissionsError(message="User lacks required permissions")

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_generic_authentication_error_returns_401():
"""Test that generic AuthenticationError is mapped to HTTP 401 Unauthorized."""
# Arrange: Create a base AuthenticationError (not a subclass)
error = AuthenticationError(message="Token has expired")

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_authentication_error_preserves_message():
"""Test that the original error message is preserved in the HTTP response."""
# Arrange: Create an error with a specific message
original_message = "Authentication failed: token signature invalid"
error = AuthenticationError(message=original_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_missing_credentials_error_preserves_message():
"""Test that MissingCredentialsError preserves its message in the response."""
# Arrange: Create an error with a specific message
original_message = "No authentication credentials provided"
error = MissingCredentialsError(message=original_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_empty_message():
"""Test handling of error with empty message string."""
# Arrange: Create an error with an empty message
error = AuthenticationError(message="")

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_very_long_message():
"""Test handling of error with very long message (1000+ characters)."""
# Arrange: Create an error with a very long message
long_message = "Error: " + ("A" * 1000)
error = InvalidCredentialsError(message=long_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_message_with_special_characters():
"""Test handling of error messages with special characters."""
# Arrange: Create an error with special characters in the message
special_message = "Error: Invalid credentials with special chars: !@#$%^&*()_+-=[]{}|;:',.<>?/~`"
error = InvalidCredentialsError(message=special_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_message_with_unicode_characters():
"""Test handling of error messages with unicode characters."""
# Arrange: Create an error with unicode characters
unicode_message = "Authentication error: Invalid token \u2013 \u65e0\u6548\u7684\u4ee4\u724c"
error = AuthenticationError(message=unicode_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_message_with_newlines():
"""Test handling of error messages with newline characters."""
# Arrange: Create an error with newlines in the message
multiline_message = "Error: Invalid credentials\nReason: Token signature mismatch\nDetails: See logs"
error = MissingCredentialsError(message=multiline_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_message_with_html_entities():
"""Test handling of error messages containing HTML-like content."""
# Arrange: Create an error with HTML-like characters
html_message = "Error: <script>alert('auth failed')</script>"
error = InvalidCredentialsError(message=html_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_message_with_quotes():
"""Test handling of error messages containing various types of quotes."""
# Arrange: Create an error with different quote types
quoted_message = 'Error: Invalid token with "double" and 'single' quotes'
error = AuthenticationError(message=quoted_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_missing_credentials_with_empty_string():
"""Test MissingCredentialsError with empty string message."""
# Arrange: Create an error with empty message
error = MissingCredentialsError(message="")

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_insufficient_permissions_with_long_message():
"""Test InsufficientPermissionsError with long message."""
# Arrange: Create an error with long message
long_message = "Permission denied: " + ("X" * 500)
error = InsufficientPermissionsError(message=long_message)

# Act: Convert the auth error to HTTP exception
codeflash_output = _auth_error_to_http(error); http_exception = codeflash_output

def test_different_subclass_types_return_correct_status_codes():
"""Test that each specific subclass returns its expected status code."""
# Arrange: Create different error types
missing_creds = MissingCredentialsError(message="test1")
invalid_creds = InvalidCredentialsError(message="test2")
insufficient_perms = InsufficientPermissionsError(message="test3")
generic_auth = AuthenticationError(message="test4")

# Act: Convert all errors
codeflash_output = _auth_error_to_http(missing_creds); http_missing = codeflash_output
codeflash_output = _auth_error_to_http(invalid_creds); http_invalid = codeflash_output
codeflash_output = _auth_error_to_http(insufficient_perms); http_insufficient = codeflash_output
codeflash_output = _auth_error_to_http(generic_auth); http_generic = codeflash_output

def test_processing_multiple_403_errors_sequentially():
"""Test processing multiple 403-triggering errors in sequence."""
# Arrange: Create a list of various 403-triggering errors
errors = [
MissingCredentialsError(message=f"Missing credentials {i}") for i in range(100)
] + [
InvalidCredentialsError(message=f"Invalid credentials {i}") for i in range(100)
] + [
InsufficientPermissionsError(message=f"Insufficient permissions {i}") for i in range(100)
]

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]

def test_processing_multiple_401_errors_sequentially():
"""Test processing multiple 401-triggering errors in sequence."""
# Arrange: Create a list of generic authentication errors
errors = [AuthenticationError(message=f"Auth error {i}") for i in range(200)]

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]

def test_processing_mixed_error_types():
"""Test processing a large batch of mixed error types."""
# Arrange: Create a mixed list of all error types
errors = []
for i in range(100):
if i % 4 == 0:
errors.append(MissingCredentialsError(message=f"Error {i}"))
elif i % 4 == 1:
errors.append(InvalidCredentialsError(message=f"Error {i}"))
elif i % 4 == 2:
errors.append(InsufficientPermissionsError(message=f"Error {i}"))
else:
errors.append(AuthenticationError(message=f"Error {i}"))

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]

# Assert: Verify correct distribution of status codes
forbidden_count = sum(1 for r in results if r.status_code == status.HTTP_403_FORBIDDEN)
unauthorized_count = sum(1 for r in results if r.status_code == status.HTTP_401_UNAUTHORIZED)

def test_large_error_messages_in_batch():
"""Test handling of errors with very large messages in batch."""
# Arrange: Create errors with increasingly large messages
large_message = "X" * 10000
errors = [
AuthenticationError(message=large_message + str(i)) for i in range(50)
]

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]

def test_error_message_uniqueness_preservation():
"""Test that unique messages are preserved across batch processing."""
# Arrange: Create errors with unique messages
messages = [f"Unique error message {i}: " + str(i * 1000) for i in range(250)]
errors = [AuthenticationError(message=msg) for msg in messages]

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]

# Assert: Verify all unique messages are preserved
result_messages = [r.detail for r in results]

def test_rapid_consecutive_conversions():
"""Test rapid consecutive conversions of the same error type."""
# Arrange: Create the same error many times
error = InvalidCredentialsError(message="Invalid API key")

# Act: Convert the error 500 times
results = [_auth_error_to_http(error) for _ in range(500)]

def test_stress_test_all_error_combinations():
"""Stress test with all possible combinations of error types and scenarios."""
# Arrange: Create a comprehensive set of errors
error_types = [
(MissingCredentialsError, status.HTTP_403_FORBIDDEN),
(InvalidCredentialsError, status.HTTP_403_FORBIDDEN),
(InsufficientPermissionsError, status.HTTP_403_FORBIDDEN),
(AuthenticationError, status.HTTP_401_UNAUTHORIZED),
]

errors = []
expected_statuses = []
for error_class, expected_status in error_types:
    for i in range(100):
        message = f"Test message {error_class.__name__} {i}"
        errors.append(error_class(message=message))
        expected_statuses.append(expected_status)

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]
for result, expected_status in zip(results, expected_statuses):
    pass

def test_return_type_consistency():
"""Test that all conversions return HTTPException with correct attributes."""
# Arrange: Create various errors
errors = [
MissingCredentialsError(message="test1"),
InvalidCredentialsError(message="test2"),
InsufficientPermissionsError(message="test3"),
AuthenticationError(message="test4"),
]

# Act: Convert all errors
results = [_auth_error_to_http(e) for e in errors]

# Assert: Verify all results are HTTPException with required attributes
for result in results:
    pass

codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-pr11639-2026-02-07T01.06.27 and push.

Codeflash

mendonk and others added 6 commits February 6, 2026 17:02
The optimized code achieves a **28% speedup** (from 76.8μs to 59.6μs) by eliminating repeated attribute lookups during runtime. 

**Key optimizations applied:**

1. **Pre-computed status codes**: The constants `_HTTP_403` and `_HTTP_401` are defined at module load time, avoiding repeated `status.HTTP_403_FORBIDDEN` and `status.HTTP_401_UNAUTHORIZED` lookups on every function call. The line profiler shows the original code spent time on status code attribute access within the HTTPException construction.

2. **Pre-defined exception tuple**: The `_FORBIDDEN_ERRORS` tuple is created once at module level instead of being reconstructed on every `isinstance()` call. While Python can optimize tuple literals, module-level definition ensures zero construction overhead per invocation.

**Why this is faster:**

In Python, attribute access (like `status.HTTP_403_FORBIDDEN`) involves dictionary lookups in the module's namespace. By caching these values as module-level constants, we perform the lookup once during import rather than on every function call. The line profiler data confirms this: the original code's `isinstance()` check (lines showing the tuple construction) consumed 15.8% of total time, while the optimized version's single `isinstance()` call takes only 11.8%.

**Performance characteristics:**

- **Best for**: High-frequency authentication error handling scenarios where this function is called repeatedly (as shown in bulk tests like `test_bulk_mapping_of_mixed_exceptions_is_correct_and_performs_well` and `test_rapid_consecutive_conversions` with 500+ iterations)
- **Scalability**: The optimization compounds with scale—processing 500 mixed exceptions benefits more than single calls
- **No behavioral changes**: All test cases pass identically, preserving edge case handling (empty messages, unicode, special characters, etc.)

The optimization is particularly valuable if this utility is in a hot path for request authentication, as even microsecond improvements multiply across thousands of API requests.
@codeflash-ai codeflash-ai Bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Feb 7, 2026
@github-actions github-actions Bot added the community Pull Request from an external contributor label Feb 7, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (docs-1.8-release@cdacc17). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@                 Coverage Diff                 @@
##             docs-1.8-release   #11645   +/-   ##
===================================================
  Coverage                    ?   35.21%           
===================================================
  Files                       ?     1521           
  Lines                       ?    72926           
  Branches                    ?    10936           
===================================================
  Hits                        ?    25681           
  Misses                      ?    45850           
  Partials                    ?     1395           
Flag Coverage Δ
backend 55.69% <100.00%> (?)
lfx 42.10% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/backend/base/langflow/services/auth/utils.py 89.55% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Base automatically changed from docs-chat-refactor-and-screenshots to docs-1.8-release February 10, 2026 16:03
@codeflash-ai codeflash-ai Bot closed this Feb 10, 2026
@codeflash-ai
Copy link
Copy Markdown
Contributor Author

codeflash-ai Bot commented Feb 10, 2026

This PR has been automatically closed because the original PR #11639 by mendonk was closed.

@codeflash-ai codeflash-ai Bot deleted the codeflash/optimize-pr11639-2026-02-07T01.06.27 branch February 10, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI community Pull Request from an external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant