AUTOMATIC1111/stable-diffusion-webui · warning · Exception

Extension with this URL is already installed: {url}

Error message

Extension with this URL is already installed: {url}

What it means

install_extension_from_url() in ui_extensions.py guards against duplicate installs: it normalizes the git URL (scheme, trailing .git, etc.) and compares it against every installed extension's remote. An exact normalized match raises this exception, while a colliding target directory is caught earlier by a separate assertion.

Source

Thrown at modules/ui_extensions.py:362

def install_extension_from_url(dirname, url, branch_name=None):
    check_access()

    if isinstance(dirname, str):
        dirname = dirname.strip()
    if isinstance(url, str):
        url = url.strip()

    assert url, 'No URL specified'

    if dirname is None or dirname == "":
        dirname = get_extension_dirname_from_url(url)

    target_dir = os.path.join(extensions.extensions_dir, dirname)
    assert not os.path.exists(target_dir), f'Extension directory already exists: {target_dir}'

    normalized_url = normalize_git_url(url)
    if any(x for x in extensions.extensions if normalize_git_url(x.remote) == normalized_url):
        raise Exception(f'Extension with this URL is already installed: {url}')

    tmpdir = os.path.join(paths.data_path, "tmp", dirname)

    try:
        shutil.rmtree(tmpdir, True)
        if not branch_name:
            # if no branch is specified, use the default branch
            with git.Repo.clone_from(url, tmpdir, filter=['blob:none']) as repo:
                repo.remote().fetch()
                for submodule in repo.submodules:
                    submodule.update()
        else:
            with git.Repo.clone_from(url, tmpdir, filter=['blob:none'], branch=branch_name) as repo:
                repo.remote().fetch()
                for submodule in repo.submodules:
                    submodule.update()
        try:
            os.rename(tmpdir, target_dir)

View on GitHub (pinned to 82a973c043)

Solutions

  1. Refresh the Extensions tab and confirm it is not already listed (it may be under a different display name)
  2. Uninstall the existing copy first (Extensions tab > Remove), then install again
  3. Manually delete/rename the folder under extensions/<dirname> if the UI cannot uninstall it, then reload
Defensive patterns

Strategy: validation

Validate before calling

from modules import ui_extensions
def already_installed(url):
    norm = ui_extensions.normalize_git_url(url.strip())
    return any(ui_extensions.normalize_git_url(x.remote) == norm for x in extensions.extensions)

Try / catch

try:
    ui_extensions.install_extension_from_url(url)
except Exception as e:
    if 'already installed' in str(e):
        pass  # idempotent install
    else:
        raise

Prevention

When it happens

Trigger: Calling Extensions > Install from URL with a repository already present in extensions/, even if installed under a different directory name (e.g. installed via --clone-from or a fork URL that normalizes identically); also re-installing after a UI cache desync where the extension exists on disk but is hidden from the list.

Common situations: Clicking install twice; a portable/backup restore where the extensions folder was copied but the UI did not refresh; URL variants like https://github.com/x/y vs git@github.com:x/y.git vs .../y.git normalizing to the same remote.

Related errors


AI-assisted analysis of AUTOMATIC1111/stable-diffusion-webui@82a973c043 (2026-08-14). Data as JSON: /api/errors/9628b756225c1d51. Report an issue: GitHub.