Skip to content

BYOK custom providers return local 403 before requests reach provider #4414

Description

@partychen

Description

Custom OpenAI- and Anthropic-compatible providers configured in the Copilot App fail every inference request with Authorization error, you may need to run /login. The session records status 403, but the failed inference request never reaches the configured provider. /login is misleading for a BYOK provider with a valid API key.

Environment

  • Copilot App / CLI binary: 1.0.79-5
  • OS: Windows 11, ARM64
  • Custom provider: self-hosted HTTPS endpoint behind Cloudflare
  • Tested: Anthropic /v1/messages and OpenAI /v1/chat/completions with completions wire API

Steps to reproduce

  1. Add a custom Anthropic provider with a valid base URL, API key, and model.
  2. Select the model and send a prompt.
  3. Observe the 403 /login error.
  4. Repeat with an OpenAI provider using a /v1 base URL and completions wire API.
  5. Observe the same failure.

Expected behavior

The app sends the request to the BYOK endpoint using the stored API key.

Actual behavior

The app reports a 403 authorization error before the request reaches the provider origin.

Diagnostics performed

  • Direct authenticated GET /v1/models, POST /v1/messages, and POST /v1/chat/completions requests succeed with HTTP 200.
  • Both affected model IDs return successful responses when called directly.
  • The app successfully calls GET /v1/models with the same configuration.
  • Windows Credential Manager contains the credential for the active provider UUID; it was compared locally and exactly matches the configured key without logging its value.
  • An explicit static Authorization: Bearer ... header does not help.
  • Recreating the provider, restarting the app, and using a fresh session do not help.
  • Origin logs show model discovery but no inference POST at the timestamp of the app-generated 403.
  • Equivalent large, streaming, tool-bearing requests outside the app reach the provider successfully.

Relevant logs

Using custom provider: type=anthropic, baseUrl=https://<provider-host>, wireApi=completions
Using custom provider: type=openai, baseUrl=https://<provider-host>/v1, wireApi=completions
{"type":"session.error","data":{"errorType":"authorization","message":"Authorization error, you may need to run /login","statusCode":403}}

No credentials or private endpoint details are included.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions