langchain-ai/deepagents · error · RuntimeError

Callback URL is missing the 'code' parameter.

Error message

Callback URL is missing the 'code' parameter.

What it means

_parse_callback_url requires an authorization `code` query parameter to exchange for tokens; a callback URL without one (and without an `error` parameter) is malformed and raises this RuntimeError. It protects against pasting the wrong URL or a truncated redirect.

Source

Thrown at libs/code/deepagents_code/mcp_auth.py:1195

    Args:
        url: Raw callback URL pasted by the user.

    Returns:
        The `code` and optional `state` query parameters.

    Raises:
        RuntimeError: If the URL contains `error=` or lacks `code`.
    """
    params = parse_qs(urlparse(url).query)
    if "error" in params:
        err_code = params["error"][0]
        err_desc = (params.get("error_description") or [""])[0]
        detail = f": {err_desc}" if err_desc else ""
        msg = f"Authorization denied by provider: {err_code}{detail}"
        raise RuntimeError(msg)
    if "code" not in params or not params["code"]:
        msg = "Callback URL is missing the 'code' parameter."
        raise RuntimeError(msg)
    return params["code"][0], (params.get("state") or [None])[0]


def _default_ui() -> OAuthInteraction:
    """Return the default `OAuthInteraction` implementation (CLI stdio)."""
    from deepagents_code.mcp_oauth_ui import CliOAuthInteraction

    return CliOAuthInteraction()


def _make_loopback_handlers(
    *,
    callback_server: _LoopbackOAuthCallbackServer,
    extra_auth_params: dict[str, str] | None = None,
    ui: OAuthInteraction | None = None,
) -> tuple[RedirectHandler, CallbackHandler]:
    """Create browser loopback redirect and callback handlers for OAuth.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Redo the login (`/mcp login <server>` / `dcode mcp login <server>`) and copy the full callback URL including ?code=...&state=...
  2. Verify the provider's registered redirect URI matches what the tool expects so the provider actually issues a code.
  3. If paste-back keeps failing, use the browser-based local callback listener instead of manual paste, or vice versa.

Example fix

// before
http://localhost:PORT/callback?state=abc            # missing code
// after
http://localhost:PORT/callback?code=xyz&state=abc   # full redirect URL from the provider
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse, parse_qs
q = parse_qs(urlparse(callback_url).query)
assert q.get("code"), "URL lacks authorization code; copy the full provider redirect URL"

Try / catch

try:
    code, state = _parse_callback_url(url)
except RuntimeError as e:
    if "missing the 'code' parameter" in str(e):
        show_user("Paste the complete redirect URL including ?code=...; restarting login.")
        restart_login_flow(server_name)
    else:
        raise

Prevention

When it happens

Trigger: callback -> _parse_callback_url receives a URL missing `code` or with an empty `code` value - e.g. the base redirect URL pasted with no query string, or a URL that only carried `state`.

Common situations: User pasted the wrong URL from the browser (e.g. the login page or a truncated address bar copy), the provider redirected without a code because of a misconfigured redirect URI, or browser extensions stripped query parameters.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/5f3fc1fcaf460060. Report an issue: GitHub.