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
- Refresh the Extensions tab and confirm it is not already listed (it may be under a different display name)
- Uninstall the existing copy first (Extensions tab > Remove), then install again
- 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
- Make install flows idempotent by checking installed remotes first
- Normalize git URLs before comparison (.git suffix, ssh vs https)
- After restoring a backup, refresh the Extensions tab before reinstalling
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.