Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ async def _start_cloud_agent(
# Custom endpoints use multipart/form-data format for direct avatar worker requests
is_custom_endpoint = not self._is_default_api_url()

if is_custom_endpoint:
if is_custom_endpoint and self._model == "expression":
# Use FormData format for custom endpoints
# Parse async parameter from URL if present
async_mode = self._parse_async_parameter_from_url()
Comment on lines +358 to 361
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 Custom endpoint with non-expression model sends JSON request with wrong auth headers to custom endpoint

When a custom endpoint is used with the "essence" model (or any non-"expression" model), the new condition is_custom_endpoint and self._model == "expression" evaluates to False, causing the code to fall through to the else branch which calls _send_json_request. This sends a JSON-formatted request with an api-secret header to the custom endpoint, but custom endpoints expect FormData format with Authorization: Bearer <token> headers (as implemented in _send_formdata_request).

Root Cause and Impact

Before this PR, the condition was simply if is_custom_endpoint, which correctly routed all custom endpoint requests to _send_formdata_request. The PR changed it to if is_custom_endpoint and self._model == "expression", meaning custom endpoints with model="essence" now incorrectly use _send_json_request.

The _send_json_request method (avatar.py:392-437) sends:

  • Content-Type: application/json header
  • api-secret header for authentication
  • JSON body format

But custom endpoints (avatar workers, Cerebrium deployments) expect:

  • multipart/form-data content type
  • Authorization: Bearer <token> header for authentication
  • FormData body format

Since _send_request_with_retry always posts to self._api_url (avatar.py:578), the request goes to the custom endpoint URL but with the wrong format and authentication, causing the request to fail.

Impact: All users with custom endpoints using the "essence" model will get request failures (likely 401 Unauthorized or 400 Bad Request) when trying to start a cloud avatar session.

(Refers to lines 358-369)

Prompt for agents
The condition at line 358 needs to be revised. The current logic sends custom endpoint + essence model requests through the JSON path (designed for the default BitHuman API), but the request still goes to the custom endpoint URL. There are two possible fixes depending on the intended behavior:

1. If custom endpoints with essence model should use FormData (like before the PR): revert the condition back to just `if is_custom_endpoint:` and handle the expression-specific logic inside `_send_formdata_request` instead.

2. If custom endpoints only support the expression model and essence should go through the default API: the else branch needs to use the default API URL instead of `self._api_url`, or raise an error explaining that custom endpoints only support the expression model.

The most likely correct fix is option 1 - keep using FormData for all custom endpoint requests regardless of model type, since the request URL and authentication mechanism are endpoint-specific, not model-specific.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Expand Down
Loading