{"record":{"id":"9628b756225c1d51","repo":"AUTOMATIC1111/stable-diffusion-webui","slug":"extension-with-this-url-is-already-installed-url","errorCode":null,"errorMessage":"Extension with this URL is already installed: {url}","messagePattern":"Extension with this URL is already installed: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"modules/ui_extensions.py","lineNumber":362,"sourceCode":"def install_extension_from_url(dirname, url, branch_name=None):\r\n    check_access()\r\n\r\n    if isinstance(dirname, str):\r\n        dirname = dirname.strip()\r\n    if isinstance(url, str):\r\n        url = url.strip()\r\n\r\n    assert url, 'No URL specified'\r\n\r\n    if dirname is None or dirname == \"\":\r\n        dirname = get_extension_dirname_from_url(url)\r\n\r\n    target_dir = os.path.join(extensions.extensions_dir, dirname)\r\n    assert not os.path.exists(target_dir), f'Extension directory already exists: {target_dir}'\r\n\r\n    normalized_url = normalize_git_url(url)\r\n    if any(x for x in extensions.extensions if normalize_git_url(x.remote) == normalized_url):\r\n        raise Exception(f'Extension with this URL is already installed: {url}')\r\n\r\n    tmpdir = os.path.join(paths.data_path, \"tmp\", dirname)\r\n\r\n    try:\r\n        shutil.rmtree(tmpdir, True)\r\n        if not branch_name:\r\n            # if no branch is specified, use the default branch\r\n            with git.Repo.clone_from(url, tmpdir, filter=['blob:none']) as repo:\r\n                repo.remote().fetch()\r\n                for submodule in repo.submodules:\r\n                    submodule.update()\r\n        else:\r\n            with git.Repo.clone_from(url, tmpdir, filter=['blob:none'], branch=branch_name) as repo:\r\n                repo.remote().fetch()\r\n                for submodule in repo.submodules:\r\n                    submodule.update()\r\n        try:\r\n            os.rename(tmpdir, target_dir)\r","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/82a973c04367123ae98bd9abdf80d9eda9b910e2/modules/ui_extensions.py#L344-L380","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"from modules import ui_extensions\ndef already_installed(url):\n    norm = ui_extensions.normalize_git_url(url.strip())\n    return any(ui_extensions.normalize_git_url(x.remote) == norm for x in extensions.extensions)","typeGuard":null,"tryCatchPattern":"try:\n    ui_extensions.install_extension_from_url(url)\nexcept Exception as e:\n    if 'already installed' in str(e):\n        pass  # idempotent install\n    else:\n        raise","preventionTips":["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"],"tags":["extensions","git","installation","duplicate"],"backgroundTag":null,"analyzedSha":"82a973c04367123ae98bd9abdf80d9eda9b910e2","analyzedAt":"2026-08-14T16:46:43.225Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}