VertexAIImagenImageEditConfig.get_complete_url was resolving vertex_project
and vertex_location only from env vars and global settings, ignoring
litellm_params. Users supplying project/location exclusively via YAML
config would get a ValueError or wrong URL even after auth headers were fixed.
Mirrors the pattern already used by VertexAIGeminiImageEditConfig and
image_generation counterpart (safe_get_vertex_ai_project/location).
Also fixes api_key type hint in MockImageEditConfig (str -> Optional[str])
and adds a test covering get_complete_url credential resolution.
Made-with: Cursor
Adds three test cases to prevent regression of the Vertex AI image_edit
credentials bug:
1. test_validate_environment_signature_includes_litellm_params: ensures
all image-edit configs accept litellm_params (contract for the handler)
2. test_vertex_gemini_image_edit_reads_credentials_from_litellm_params:
verifies Gemini config reads from litellm_params first
3. test_vertex_imagen_image_edit_reads_credentials_from_litellm_params:
verifies Imagen config reads from litellm_params first
These tests catch if the fix is accidentally reverted or if new image-edit
configs are added without the litellm_params parameter.
Made-with: Cursor
When aimage_edit or image_edit was called with Vertex AI Gemini/Imagen models
via YAML-style config (vertex_project / vertex_credentials in proxy YAML),
the credentials were dropped during handler-to-config plumbing, causing
fallback to Application Default Credentials and DefaultCredentialsError.
Root cause: image_edit_handler and async_image_edit_handler did not pass
litellm_params to validate_environment, unlike image_generation_handler.
Fixes:
1. Widen BaseImageEditConfig.validate_environment signature to accept
litellm_params and api_base (optional kwargs).
2. Forward dict(litellm_params) and litellm_params.api_base from both
sync and async image_edit handlers to validate_environment.
3. Update VertexAIImagenImageEditConfig.validate_environment to read
vertex_ai_project/vertex_ai_credentials from litellm_params first,
matching Gemini config pattern (secondary latent bug fix).
4. Widen all image-edit config override signatures to match base.
Made-with: Cursor
Per-user OAuth MCP requests now only skip pre-emptive 401 when a stored token is available, preserving token-reuse behavior while restoring fast PKCE kickoff for first-time or missing-token users.
Made-with: Cursor
- Add _verify_org_access to deprecated POST /organization/info endpoint
- Move get_user_object to module-level import in organization_endpoints.py
- Add tests for _verify_team_access 403 denial path
- Introduced a new method in `FileContentStreamingHandler` to resolve streaming request parameters, enhancing the routing logic based on credentials.
- Updated the `should_stream_file_content` method to check against supported providers.
- Cleaned up type hints and imports across multiple files for better organization and clarity.
- Added comprehensive tests to validate the new routing behavior and ensure original data integrity during streaming requests.
* fix(s3): add retry with exponential backoff for transient S3 503/500 errors
S3 occasionally returns 503 "Slow Down" during PUT operations when
request rates spike above partition limits. The current code makes a
single upload attempt via httpx — unlike boto3, httpx has no built-in
retry for transient S3 errors. Failed uploads permanently lose the
request's audit/logging data.
Add exponential backoff retry (3 attempts, 1s/2s delays) for S3
500/503 responses in both async_upload_data_to_s3 and
upload_data_to_s3. Logs a warning on each retry with the S3 object
key for observability.
In production we observed ~18 permanent S3 upload failures per day
(124 over 7 days) — all transient 503s that would have succeeded on
a single retry.
* test(s3): add unit tests for S3 upload retry logic
Tests cover:
- Async retry on 503 (succeeds on second attempt)
- Async retry on 500
- Exhausted retries on persistent 503 (calls handle_callback_failure)
- No retry on 4xx errors (403)
- Sync retry on 503
* style(s3): move time import to module level
Address review feedback: move `import time` from inside
upload_data_to_s3 to the top-level imports per project style guide.
* fix(logging): preserve proxy key-auth metadata on /v1/messages Langfuse traces
update_from_kwargs() overwrites proxy metadata (user_api_key_hash, etc.)
with Anthropic's native metadata when both exist. Merge instead of replace.
* fix(test): update stale assertion for new metadata merge semantics
* test: add explicit conflict-resolution test for metadata merge
* feat(containers): Azure container routing, managed IDs, and delete response wire format
- Add AzureContainerConfig and safe URL joining for paths with api-version query
- Encode/decode managed container IDs in responses, streaming, and proxy handlers
- Accept OpenAI delete response object literal container.file.deleted
- Tests for Azure URL regression and DeleteContainerFileResponse parsing
Made-with: Cursor
* fix(responses): gate response id update on parsed_chunk having response
Delta stream events do not include a response body; Mock-based tests
(and any truthy synthetic .response on transforms) must not trigger
_update_responses_api_response_id_with_model_id. Fixes
test_stop_async_iteration_not_logged_as_failure (TypeError: Mock not iterable).
Made-with: Cursor
* feat(containers): encode container IDs in SDK responses for routing
- Add ContainerRequestUtils.encode_container_id_in_response utility
- Encode container_id in create/retrieve/delete responses (SDK path)
- Fix streaming iterator: gate response ID update on parsed_chunk key
- Follows responses API pattern (encode after handler, not in handler)
Made-with: Cursor
* fix(containers): module-level imports and managed cntr_ ID encoding
- Move ResponsesAPIRequestUtils imports to module scope (utils, main, handler_factory).
- Serialize absent model_id as empty segment instead of literal None; decode empty
and legacy "None" segments as missing for router affinity.
- Add unit tests for build/decode round-trip and legacy IDs.
Made-with: Cursor
* fix(containers): decode managed IDs in endpoint_factory SDK path
- Add decode_managed_container_id_for_request in containers/utils and reuse from main.
- Strip LiteLLM cntr_ wrappers before generic_container_handler (64-char API limit).
- Resolve provider for logging/errors; add unit test for decode helper.
- Use resolved_custom_llm_provider after decode for mypy-safe provider typing.
Made-with: Cursor
* Fix p1 concern
* Fix p1 concern
When modify_params is true, Bedrock Converse setup no longer prepends or
appends the default user message if the boundary assistant turn has
prefix: true, so OpenAI-style assistant prefill reaches the API unchanged.
Made-with: Cursor
* feat(guardrails): optional skip system message in unified guardrail inputs
Made-with: Cursor
* feat(dashboard): skip_system_message_in_guardrail in guardrail UI
Add a tri-state control (inherit / yes / no) when creating or editing
guardrails so admins can set litellm_params.skip_system_message_in_guardrail
without YAML. Table edit merges existing litellm_params before PUT to avoid
wiping content-filter and other provider fields.
Document the dashboard flow in the guardrails quick start with a screenshot.
Made-with: Cursor
* fix(guardrails): type structured_messages as AllMessageValues for mypy
Use AllMessageValues in openai_messages_without_system and cast adapter
request messages so GenericGuardrailAPIInputs matches TypedDict.
Made-with: Cursor
* fix(responses): map refusal stop_reason to incomplete status in streaming
Fixes streaming responses API translation where Anthropic's stop_reason="refusal"
was incorrectly translated to status="completed" instead of "incomplete".
Root cause: build_base_response was unconditionally overwriting finish_reason
with None from later chunks, losing the terminal content_filter value.
Changes:
- streaming_chunk_builder_utils: skip None finish_reason values in build_base_response
- streaming_iterator: snapshot chunks before returning pending events (sync path)
- streaming_handler: treat usage-only chunks as meaningful content
- transformation: map finish_reason=refusal to status=incomplete
- tests: add regression tests for refusal handling
Made-with: Cursor
* Fix test
- Changed the import path for `upload_file_to_storage_backend` in test files to reflect the new module structure.
- Ensured consistency in mocking for storage backend service tests.
The raw SQL queries in spend_management_endpoints.py, spend_tracking_utils.py,
and analytics_endpoints.py cast date params to ::timestamptz while comparing
against the plain-timestamp "startTime" column. Postgres resolves the type
mismatch by promoting the column using the DB session timezone, which drifts
the filter window and date_trunc buckets whenever session TZ is not UTC —
silently dropping rows at UTC day boundaries and, for narrow windows, losing
rows entirely.
Wraps every such comparison with `AT TIME ZONE 'UTC'` so the param side
resolves to a plain timestamp matching the column type. Both sides end up
as plain timestamp, Postgres does no implicit conversion, and session TZ
plays no role in the query. The fix is constant-foldable so the existing
startTime index (PR #17504) remains usable.
Also marks strptime-produced datetimes as tz-aware UTC at the call sites
for intent clarity and consistency with parse_date.
Fixes#22529 (Logs page missing recent rows under non-UTC session TZ) and
the Global Usage single-day-returns-two-days symptom reported internally.
- Added validation to ensure credentials include a custom LLM provider before routing.
- Cleaned up type casting for better readability.
- Introduced a new test to verify behavior when a non-OpenAI provider is used, ensuring proper handling of streaming responses.
- Updated imports to include necessary modules for testing.
- Updated `FileContentStreamingHandler` to utilize `custom_llm_provider` from credentials for routing.
- Added error handling for missing `custom_llm_provider` in credentials.
- Introduced new tests to validate streaming behavior with routed providers and non-OpenAI providers.
- Cleaned up imports and ensured proper type casting for improved clarity.
- Static Methods for Streaming Handler Function
- Remove the afile_content_streaming wrapper function. Enabled with a stream boolean in afile_content
- Cleaned up test cases after refactor
- Removed unused imports and streamlined type hints in `litellm/utils.py` and `litellm/files/main.py`.
- Moved `FileContentStreamingResult` to a new `litellm/files/types.py` for better organization.
- Updated `FileContentStreamingResponse` in `litellm/files/streaming.py` to include asynchronous close methods and improved logging capabilities.
- Enhanced tests to ensure proper closure of streaming iterators in `tests/test_litellm/llms/openai/test_openai_file_content_streaming.py` and `tests/test_litellm/proxy/openai_files_endpoint/test_files_endpoint.py`.