Skip to content

fix: function invocation 405s on EU/self-hosted (strip /v1/proxy from proxy_conn)#541

Merged
Abhijeet Prasad (AbhiPrasad) merged 1 commit into
mainfrom
fix/eu-proxy-url-function-invoke
Jul 6, 2026
Merged

fix: function invocation 405s on EU/self-hosted (strip /v1/proxy from proxy_conn)#541
Abhijeet Prasad (AbhiPrasad) merged 1 commit into
mainfrom
fix/eu-proxy-url-function-invoke

Conversation

@paultancre-bt

@paultancre-bt paultancre-bt commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Issue

Function invocation on EU (and self-hosted) data planes fails with 405 Method POST not supported (Pylon #18531; originally reported on the TypeScript SDK, but the Python SDK has the identical bug).

function/invoke, function/sandbox-list, and function/code are all POSTed through proxy_conn. For EU/self-hosted orgs the login response sets proxy_url = {api_url}/v1/proxy, but these function/* endpoints are served at the API host root, not under /v1/proxy. So the SDK posts to .../v1/proxy/function/invoke → 405.

US multi-tenant orgs avoid this by accident: their stored proxy_url is null, so login falls back to the bare api_url (no /v1/proxy), which routes correctly.

Repro on current version

Login on an EU org returns proxy_url = https://api-eu.braintrust.dev/v1/proxy, and proxy_conn().post("function/invoke", ...) posts under it:

POST target Result
api-eu.braintrust.dev/v1/proxy/function/invoke (current SDK) 405 Method POST not supported
api-eu.braintrust.dev/function/invoke (API host root) 400 — routed, POST accepted

Fix

Normalize the proxy_conn base URL by stripping a trailing /v1/proxy, so function/* requests resolve at the API host root on every data plane. state.proxy_url is left untouched.

No endpoint-level regression

Every endpoint that flows through proxy_conn was probed against both bases — all route at the bare host, all 405 under /v1/proxy today:

Endpoint bare host /v1/proxy
function/invoke 400 ✓ routed 405 ✗
function/sandbox-list 500 ✓ routed 405 ✗
function/code 400 ✓ routed 405 ✗

The OpenAI-compatible proxy path (chat/completions) does not go through proxy_conn, so the /v1/proxy suffix it relies on is unaffected.

Tests

Added proxy_conn normalization tests in test_logger.py. Verified end-to-end against a live EU org: login returns .../v1/proxy, proxy_conn().base_url now resolves to the bare host.

Note

A server-side fix (not stamping /v1/proxy into org.proxy_url for EU/self-hosted, matching US) would also fix already-released SDK versions; this SDK change helps users who upgrade.

Function invocation, sandbox listing, and code push all POST through
proxy_conn. For EU/self-hosted orgs the login response sets proxy_url to
`{api_url}/v1/proxy`, but these `function/*` endpoints are served at the API
host root, so requests hit `.../v1/proxy/function/invoke` and return 405
"Method POST not supported". US multi-tenant orgs avoid this only because
their proxy_url falls back to the bare api_url.

Normalize the proxy_conn base URL by stripping a trailing /v1/proxy.
state.proxy_url is left untouched so nothing else that reads it changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@AbhiPrasad

Copy link
Copy Markdown
Member

do we have to make the sdk fix here? Can't we just fix this server-side?

@paultancre-bt

Copy link
Copy Markdown
Contributor Author

Abhijeet Prasad (@AbhiPrasad) Given that's the unique report I deferred to limit the fix to a new version of the SDK (same as braintrustdata/braintrust-sdk-javascript#2180) but up to you to decide if this would be better on a server side fix.

@AbhiPrasad Abhijeet Prasad (AbhiPrasad) merged commit 5324d30 into main Jul 6, 2026
82 checks passed
@AbhiPrasad Abhijeet Prasad (AbhiPrasad) deleted the fix/eu-proxy-url-function-invoke branch July 6, 2026 16:21
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.

2 participants