Skip to content

Reject unknown gateway provider ids and surface unavailable alias reasons - #599

Merged
kfallah merged 5 commits into
mainfrom
devin/1787430991-reject-unknown-gateway-providers
Aug 22, 2026
Merged

Reject unknown gateway provider ids and surface unavailable alias reasons#599
kfallah merged 5 commits into
mainfrom
devin/1787430991-reject-unknown-gateway-providers

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

exp config gateway provider add NAME --provider openai_compatible (underscore) previously stored the bogus provider id, alias create snapshotted a catalog referencing it, and the alias then failed silently at gateway startup: every request answered 503 {"code":"unavailable_route"} with no hint of the misconfiguration.

Two changes, both driven by the runtime registry's single authoritative provider set:

  • The registry's private _SUPPORTED_PROVIDERS is now exported as SUPPORTED_PROVIDERS from exp.runtime.models, and provider admission fails closed on any id the gateway cannot serve, listing every servable provider. Servable means SUPPORTED_PROVIDERS - GATEWAY_EXCLUDED_PROVIDERS, where the exclusion set ({"tinker"}) is exported from exp.common.models.gateway_catalog and reused by normalize_gateway_catalog, so admission and deployment normalization cannot drift. The check lives in a shared require_gateway_servable_provider in management.py and is enforced at both mutation seams: GatewayManagement.upsert_provider_connection (covers provider add, provider update, and other management callers) and SQLiteGatewayPlatform.mutate_provider_connection (the exported platform API). The CLI's existing usage_error(ValueError, ...) context turns the GatewayStoreError into a clear parameter error:
$ exp config gateway provider add mistyped --provider openai_compatible ...
Error: provider connection 'mistyped' uses unsupported provider 'openai_compatible';
choose one of: anthropic, azure, bedrock, gemini, openai, openai-compatible, openrouter
  • Partial startup is now diagnosable: _load_alias_state keeps its (alias, reason) failures on _AliasAuthorityState.unavailable_aliases, which flows to LocalGatewayComponents.unavailable_aliases and LocalGatewayRuntime.unavailable_aliases. exp serve (both python and rust engines) emits each failed alias in the JSON startup receipt as unavailable_aliases: [{alias, reason}] and in human output as a literal (markup-disabled) warning naming the alias, its 503 unavailable_route behavior, and the exact reason. The all-aliases-failed path still raises GatewayLifecycleError as before.

lifecycle.py and platform.py sit at the 999-line hand-authored limit, so a few adjacent blocks were condensed (shared _authority_key helper, single-line message joins, tightened docstrings) without behavior change.

Regression tests: provider_test.py (CLI add/update rejection and accept path), management_test.py (fail-closed upsert, error lists every servable provider, tinker rejected), platform_test.py (platform mutation rejects tinker and persists nothing), lifecycle_test.py (partial startup exposes each failed alias with its reason), serve_test.py (receipt shaping and human warning output).

Note: terminal_tasks_live_pipeline_test.py and release_test.py::test_installed_wheel_no_spend_release_evidence fail in this dev environment on clean main too (local AZURE_OPENAI_ENDPOINT binding); unrelated to this change. All other gates pass: ruff check, ruff format, ty, pytest.

Link to Devin session: https://app.devin.ai/sessions/8ffbe9ab84124f65a44b7eceb5f3879b
Requested by: @kfallah

kfallah and others added 2 commits August 22, 2026 20:36
…sons

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Tested this end-to-end at the CLI level against a fresh gateway root:

Invalid provider id now fails closed

$ exp config gateway provider add bad --provider openai_compatible --credential-env OPENAI_API_KEY --non-interactive --json --root /tmp/exproot
Error: provider connection 'bad' uses unsupported provider 'openai_compatible';
choose one of: anthropic, azure, bedrock, gemini, openai, openai-compatible, openrouter, tinker
(exit 2, provider list --json => "items":[])

Canonical openai-compatible with --base-url still adds fine.

Partial-failure startup diagnosability (two openai-compatible providers, one with a missing credential env, one alias granted on each):

JSON receipt now names the broken alias and exact reason:

{"operation":"gateway.run","status":"ready","engine":"rust", ...,
 "unavailable_aliases":[{"alias":"brokenalias","reason":"connection credential environment variable 'MISSING_KEY_XYZ' is not set and no stored credential exists for connection 'broken'"}]}

Human startup prints the warning:

Gateway ready (rust engine) http://127.0.0.1:8124/v1
! alias 'brokenalias' is unavailable and will answer 503 unavailable_route:
connection credential environment variable 'MISSING_KEY_XYZ' is not set and no
stored credential exists for connection 'broken'
Regression: healthy alias still serves
model "healthy"     -> HTTP 200, real completion + usage accounting
model "brokenalias" -> HTTP 503 {"code":"unavailable_route"}

All assertions passed.

@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR rejects provider identifiers that cannot produce gateway deployments and exposes partially unavailable aliases in startup diagnostics.

  • Exports the runtime provider registry and centralizes gateway-servable provider validation across management and platform mutation APIs.
  • Shares the Tinker exclusion between provider admission and catalog normalization.
  • Propagates unavailable alias names and reasons through Python and Rust startup receipts and human-readable warnings.
  • Adds regression coverage for CLI validation, management and platform mutation, lifecycle propagation, and startup output.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
exp/runtime/gateway/management.py Adds shared fail-closed validation against the registry-supported, gateway-servable provider set.
exp/runtime/gateway/sqlite/platform.py Applies the shared provider validation to public platform upserts while preserving disable behavior.
exp/common/models/gateway_catalog.py Exports and reuses the provider exclusion set so admission and normalization agree about Tinker.
exp/runtime/gateway/lifecycle.py Retains unavailable alias reasons in loaded authority state and propagates them through local gateway composition.
exp/cli/gateway/serve.py Adds unavailable alias details to both engine receipts and emits literal, markup-disabled human warnings.
exp/runtime/models/registry.py Promotes the runtime-supported provider set to a public constant without changing registry membership.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Provider mutation] --> B{Provider is registry-supported and gateway-servable?}
  B -- No --> C[Reject configuration]
  B -- Yes --> D[Persist provider authority]
  D --> E[Load granted aliases]
  E --> F{Alias loads successfully?}
  F -- Yes --> G[Publish ready route]
  F -- No, while another route is ready --> H[Publish unavailable alias reason]
  F -- No routes ready --> I[Fail gateway startup]
Loading

Reviews (4): Last reviewed commit: "Keep the platform adapter within the han..." | Re-trigger Greptile

Comment thread exp/runtime/gateway/management.py Outdated
Comment thread exp/cli/gateway/serve.py
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Comment thread exp/runtime/gateway/management.py Outdated
kfallah and others added 2 commits August 22, 2026 21:22
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@kfallah
kfallah merged commit de72f72 into main Aug 22, 2026
14 checks passed
@kfallah
kfallah deleted the devin/1787430991-reject-unknown-gateway-providers branch August 22, 2026 22:01
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.

1 participant