Skip to content

[BUG]: Add Gateway fails with pattern validation error for auth types other than "Query Parameter" #5064

@nickmarden

Description

@nickmarden
Image Image

Description

Submitting the "Add New MCP Server or Gateway" form with any authentication type (Bearer, Basic, OAuth 2.0, etc.) fails with:

String should match pattern '^[a-zA-Z_][a-zA-Z0-9_-]*$'

The error gives no field name, making it appear as though the gateway name or URL is invalid when it is not.

Steps to reproduce

  1. Open the Admin UI → Gateways tab
  2. Click Add Gateway
  3. Fill in MCP Server Name and MCP Server URL
  4. Set Authentication Type to anything other than "Query Parameter (INSECURE)" — e.g. OAuth 2.0 or Bearer Token
  5. Click Add Gateway
  6. Observe the error banner above the form

Root cause

HTML layer: The form contains a hidden <div id="auth-query_param-fields-gw"> with an <input name="auth_query_param_key"> inside it. The div is toggled visible/hidden via style.display by handleAuthTypeChange() in auth.js, but the input is never disabled. Browsers submit all enabled inputs regardless of visibility, so auth_query_param_key="" is always included in the POST body.

Server layer: _parse_gateway_data_from_request() in admin.py collects every non-None form field into the data dict:

for key in form.keys():
    value = form.get(key)
    if value is not None:
        data[key] = value

An empty string is not None, so auth_query_param_key: "" reaches GatewayCreate(**data). Pydantic then rejects "" against the field's pattern=r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" constraint and raises a ValidationError.

The gateway update path already handles this correctly (str(form.get("auth_query_param_key", "")) or None), but the create path goes through the shared parser which lacks the same normalization.

Fix (two-layer)

  1. admin.py / _parse_gateway_data_from_request — after form parsing, convert empty strings to None for auth_query_param_key and auth_query_param_value before the data reaches Pydantic. Mirrors what the update handler already does; provides server-side defense in depth regardless of frontend state.

  2. admin_ui/auth.js / handleAuthTypeChange — disable inputs inside sections being hidden and re-enable them when shown. Stops the spurious empty-string fields from reaching the server in the first place.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions