bytedance/deer-flow · error · HTTPException

An account with this email already exists. Contact your admi

Error message

An account with this email already exists. Contact your administrator to link it to your SSO account.

What it means

HTTP 409 raised when a local (password) account already owns the email and no OAuth link exists. DeerFlow deliberately never auto-links an SSO identity onto a pre-existing local account, because whoever controls the IdP's email namespace could otherwise take over a password account that happens to share the address. The fix requires an administrator to link them out-of-band.

Source

Thrown at backend/app/gateway/auth/user_provisioning.py:73

    email = identity.email.lower()

    # 3. Domain restriction
    if provider_config.allowed_email_domains:
        domain = email.rsplit("@", 1)[-1]
        if domain not in {d.lower().lstrip("@") for d in provider_config.allowed_email_domains}:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Your email domain is not allowed. Please use an approved email address.",
            )

    # 4. Block if a local account already owns this email. We never auto-link an
    # SSO identity onto a pre-existing local account, since that would let an SSO
    # login take over a password account that happens to share the email.
    local_user = await local_provider.get_user_by_email(email)

    if local_user:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=("An account with this email already exists. Contact your administrator to link it to your SSO account."),
        )

    # 5. Auto-create
    if not provider_config.auto_create_users:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Automatic account creation is disabled. Contact your administrator.",
        )

    role = _resolve_role(email, provider_config.admin_emails)
    try:
        user = await local_provider.create_oauth_user(
            email=email,
            oauth_provider=provider_id,
            oauth_id=identity.subject,
            system_role=role,

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Have an administrator link the SSO identity to the existing local account (out-of-band admin action, e.g. admin UI/CLI link operation)
  2. If the local account is stale, remove or rename it so provisioning can auto-create
  3. Log in with the local (password) credentials instead
Defensive patterns

Strategy: try-catch

Validate before calling

local_user = await local_provider.get_user_by_email(identity.email.lower())
linked = await local_provider.get_user_by_oauth(provider_id, identity.subject)
if local_user and not linked:
    return RedirectResponse("/login?error=account_exists_contact_admin")

Try / catch

try:
    await provision_oauth_user(provider_id, identity, provider_config)
except HTTPException as e:
    if e.status_code == 409 and "already exists" in e.detail:
        return page("contact-admin-to-link")  # never auto-link in code either
    raise

Prevention

When it happens

Trigger: First SSO login by a user who previously registered a local password account with the same email (case-insensitively matched via get_user_by_email). Reached after the verified-email, email-present, and domain checks pass.

Common situations: Enabling SSO on an installation that already has password users; a user signing in with SSO before their admin-performed link; email reused across local and IdP accounts.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/db70ae1e3463956c. Report an issue: GitHub.