Skip to content

[Bug] GitHub Copilot model request fails with 502 and TLS hostname mismatch #553

Closed as not planned

Description

@burhiepotdult1982

Client or integration

Codex App

Area

Provider adapter

Summary

Requests using a GitHub Copilot-backed model intermittently fail with HTTP 502. The OpenCodex proxy reports ERR_TLS_CERT_ALTNAME_INVALID while fetching the GitHub Copilot API. I expected the request to complete successfully or return a provider-level error, not a TLS certificate hostname mismatch.

Reproduction

  1. Run OpenCodex locally on port 10100.
  2. Configure the Codex App to use the OpenAI-compatible endpoint http://127.0.0.1:10100/v1.
  3. Select the GitHub Copilot-backed model github-copilot/claude-sonnet-4.
  4. Send a normal chat/request.
  5. The request fails with HTTP 502.

Observed error:

unexpected status 502 Bad Gateway: Provider unreachable: ERR_TLS_CERT_ALTNAME_INVALID fetching https://api.individual.githubcopilot.com/chat/completions. For more information, pass verbose: true in the second argument to fetch(), url: http://127.0.0.1:10100/v1/responses

The failure appears to occur in the provider adapter when translating /v1/responses to the Copilot Chat Completions endpoint.

Version

2.7.41

Operating system

macOS 26.5.1 (Build 25F80), Apple Silicon

Provider and model

github-copilot/claude-sonnet-4

Logs or error output

unexpected status 502 Bad Gateway: Provider unreachable: ERR_TLS_CERT_ALTNAME_INVALID fetching https://api.individual.githubcopilot.com/chat/completions. For more information, pass verbose: true in the second argument to fetch(), url: http://127.0.0.1:10100/v1/responses

Screenshots and supporting files

No response

Redacted configuration

[proxy]
base_url = http://127.0.0.1:10100/v1
provider = GitHub Copilot
model = github-copilot/claude-sonnet-4

No credentials or tokens included.

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

  1. github-actions commented on Jul 27, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: unknown.

  2. added
    needs-infoWaiting on reporter for a concrete spec or reproduction
    on Jul 27, 2026
  3. Ingwannu commented on Jul 27, 2026

    @Ingwannu
    Owner

    I checked the exact reported hostname and current dev transport path. OpenCodex accepts the OAuth token's allowlisted *.githubcopilot.com API endpoint, so https://api.individual.githubcopilot.com/chat/completions is an expected Copilot endpoint rather than a malformed URL.

    I cannot reproduce the TLS failure now:

    • api.individual.githubcopilot.com currently resolves to 140.82.112.21 here.
    • Its certificate SAN contains *.individual.githubcopilot.com and individual.githubcopilot.com.
    • curl completes TLS successfully (the unauthenticated HEAD then returns the expected HTTP 405).
    • Bundled Bun 1.3.14 completed 20 alternating TLS requests to api.githubcopilot.com and api.individual.githubcopilot.com without a hostname error.

    That makes a deterministic adapter URL bug unlikely. The remaining possibilities are a transient upstream certificate rollout, local/VPN/custom-DNS/antivirus TLS interception, or a resolver-specific endpoint.

    Please capture the following on the affected Mac immediately after a failure (no tokens are involved):

    curl -Iv https://api.individual.githubcopilot.com/chat/completions
    openssl s_client -connect api.individual.githubcopilot.com:443 \
      -servername api.individual.githubcopilot.com </dev/null 2>/dev/null \
      | openssl x509 -noout -subject -issuer -ext subjectAltName

    Also include the failure timestamp/time zone and whether a VPN, proxy, custom DNS, or HTTPS-inspecting security product is active. If curl shows the wrong certificate too, this is outside the adapter; if curl is clean while OpenCodex fails at the same moment, we can isolate the Bun connection path. Marking needs-info and leaving it open rather than changing TLS validation or disabling certificate checks.

  4. burhiepotdult1982 commented on Jul 28, 2026

    @burhiepotdult1982
    Author

    I reproduced the TLS hostname mismatch on the affected Mac and captured the requested output. Shadowrocket TUN and the company Yunshu/VPN were active during the test. No tokens or credentials were included.

    During the failing run:

    • api.individual.githubcopilot.com resolved to 198.18.0.17, which is in the Shadowrocket Fake-IP range.
    • TLS completed, but the server certificate was CN=*.mail.163.com (NetEase).
    • The certificate SAN did not include api.individual.githubcopilot.com, and curl exited with error 60: no alternative certificate subject name matches the target host.

    I then repeated the same test at 2026-07-28 01:40 GMT+8. The result was different:

    • The hostname resolved to 198.18.0.34, also in the Fake-IP range.
    • The certificate was CN=*.individual.githubcopilot.com, issued by Sectigo, and the SAN matched api.individual.githubcopilot.com.
    • TLS verification succeeded and the endpoint returned HTTP/2 405 with Allow: POST, which is expected because the test used HEAD.

    This confirms an intermittent local TUN/VPN/DNS or routing/certificate-interception problem rather than a deterministic malformed Copilot URL. The successful retest also shows that the current path can serve the correct Copilot certificate. I will continue with an actual POST request through OpenCodex if needed. The exact wall-clock timestamp of the first failing run was not recorded.

  5. lidge-jun commented on Jul 28, 2026

    @lidge-jun
    Owner

    Status: PR #575 improves attribution, but does not resolve the TLS mismatch

    To set expectations correctly on what is in flight here.

    PR #575 is open and mergeable. It makes the proxy distinguish a TLS hostname mismatch from an unreachable provider, so ERR_TLS_CERT_ALTNAME_INVALID stops being reported as a generic upstream failure and carries a recovery hint instead.

    That changes what you are told, not what happens. The underlying condition in your capture — api.individual.githubcopilot.com resolving to 198.18.0.17 while Shadowrocket TUN and the corporate VPN were active, so the presented certificate does not cover the requested hostname — is an interception/routing condition outside the proxy. Merging #575 will not make that request succeed, and this issue should not be closed by it.

    Keeping this open for that reason. If you can retest with the TUN and VPN disabled and confirm the same request succeeds, that would confirm the split cleanly and tell us whether anything remains on our side beyond the error message.

  6. lidge-jun commented on Jul 29, 2026

    @lidge-jun
    Owner

    Status update: #575 is merged (fff8c369f), and as stated earlier it does not close this issue.

    What changed is the diagnosis you get. The proxy now separates a TLS certificate/hostname mismatch from an unreachable provider, so instead of

    Provider unreachable: ERR_TLS_CERT_ALTNAME_INVALID fetching https://api.individual.githubcopilot.com/chat/completions
    

    you get a message that names the host, states that opencodex did not rewrite it, and gives the command that settles which certificate is actually being served. That removes the misreading this issue was originally filed on — that the adapter was mangling the Copilot URL. It was not: *.githubcopilot.com is an allow-listed Copilot endpoint.

    What has not changed is your actual failure. In your capture api.individual.githubcopilot.com resolved to 198.18.0.17 with Shadowrocket TUN and the corporate VPN active, so the presented certificate does not cover the requested hostname. That is an interception/routing condition ahead of the proxy, and no proxy-side change makes that request succeed.

    So this stays open on the original ask. The retest that would settle it is unchanged: with TUN and the VPN disabled, confirm the same request succeeds. If it does, this closes as environmental. If it still fails with the certificate mismatch on a clean network path, that would be new information and worth digging into.

    One incidental note, since it touched the same code path: the old message echoed the fetched URL verbatim, and a provider base URL can carry credentials as https://user:token@host/. Both branches now redact userinfo, so an error string can no longer hand back a token. Not your report, but it was found while rewriting this message and is worth knowing if you have ever pasted an error containing a base URL.

  7. removed
    needs-infoWaiting on reporter for a concrete spec or reproduction
    on Jul 30, 2026
  8. added
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    on Aug 1, 2026
  9. lidge-jun commented on Aug 2, 2026

    @lidge-jun
    Owner

    Triage status: the evidence so far points at local VPN/fake-IP interception (Shadowrocket-class) rather than the proxy — #575 already fixed the attribution side. Could you retest on a clean network (VPN fully disabled)? If it still fails there, please capture the TLS handshake hostname from the failing request and we will reopen the investigation.

  10. lidge-jun commented on Aug 2, 2026

    @lidge-jun
    Owner

    Triage: the proxy now classifies TLS-interception-shaped connect failures explicitly (src/server/responses/upstream-error.ts:18, tests/upstream-connect-error.test.ts), but the reported VPN/fake-IP certificate mismatch itself is environmental and cannot be prevented proxy-side. Leaving open for the documentation/improved-guidance track.

  11. lidge-jun commented on Aug 3, 2026

    @lidge-jun
    Owner

    Closing this as an environment fault rather than an opencodex defect, on the evidence you supplied yourself.

    Your own diagnostics showed a Shadowrocket fake-IP DNS route returning a NetEase certificate for the Copilot hostname, and a later route returning the correct Copilot certificate. That is TLS interception on the path, not a hostname rewrite in the adapter. The Copilot transport accepts only HTTPS *.githubcopilot.com endpoints (src/providers/github-copilot-transport.ts:43) and deliberately does not relax certificate verification to accommodate an intercepting proxy — doing so would silently accept a man-in-the-middle for every user.

    What did change since you filed: PR #575 (fff8c369f) added TLS-interception identification with an SNI probe at src/server/responses/upstream-error.ts:18-25, so the same failure now reports what it actually is instead of surfacing as a bare 502. That fixed the diagnosis, not the connection — and the connection was never ours to fix.

    If you hit ERR_TLS_CERT_ALTNAME_INVALID again on a route where you are not running an intercepting proxy, please reopen with the certificate subject from the probe output. That would be a different problem and worth tracking.

    Thanks for the certificate captures — they made this unambiguous.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingproviderProvider adapters, OpenAI-compat presets, upstream API quirks

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions