{"record":{"id":"3ab59bf88b81370b","repo":"github/spec-kit","slug":"could-not-install-extension-from-downloaded-archiv","errorCode":null,"errorMessage":"Could not install extension from downloaded archive: {exc}","messagePattern":"Could not install extension from downloaded archive: (.+?)","errorType":"exception","errorClass":"ExtensionError","httpStatus":null,"severity":"error","filePath":"src/specify_cli/extensions/_commands.py","lineNumber":217,"sourceCode":"            raise ExtensionError(\n                f\"{url} did not return a ZIP archive or tar.gz/tgz archive \"\n                f\"(got {len(archive_data)} bytes). This usually means the request \"\n                \"was not authenticated and a login/HTML page was returned. \"\n                \"Verify the URL and configured credentials.\"\n            ) from exc\n\n        # Consume the transient inode reserved above rather than reopening the\n        # cache pathname during extraction.\n        try:\n            return manager.install_from_zip(\n                archive_path,\n                speckit_version,\n                priority=priority,\n                force=force,\n                archive_file=download_file,\n            )\n        except OSError as exc:\n            raise ExtensionError(\n                f\"Could not install extension from downloaded archive: {exc}\"\n            ) from exc\n    finally:\n        if download_file is not None:\n            try:\n                download_file.close()\n            except OSError:\n                pass\n        elif download_fd >= 0:\n            try:\n                os.close(download_fd)\n            except OSError:\n                pass\n\n\ndef _load_catalog_command_config(project_root: Path, config_path: Path) -> dict:\n    \"\"\"Load extension catalog CLI config with user-facing shape errors.\"\"\"\n    try:","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/src/specify_cli/extensions/_commands.py#L199-L235","documentation":"The archive passed format detection, but manager.install_from_zip raised a plain OSError during extraction or installation (the ExtensionError paths of install_from_zip propagate as-is; only OSError gets this wrapper). This is a filesystem-level failure during unpacking or copying into .specify/extensions — permissions, disk space, path length, or exotic archive member metadata.","triggerScenarios":"Thrown at src/specify_cli/extensions/_commands.py:217 when the library encounters an invalid state.","commonSituations":"Disk filling up while extracting a large extension; read-only or permission-restricted .specify; archives containing absolute paths or device entries that the extractor's safe-copy layer struggles with; long paths on Windows.","solutions":["Read the chained cause (`exc.__cause__`) — the errno pinpoints ENOSPC vs EACCES vs anything else","Free disk space (extraction roughly doubles the archive footprint)","Fix permissions on the project/.specify tree so extraction and copy can write","On Windows, enable long-path support or move the project shallower if errno relates to path length","Repackage the extension without unusual entries (absolute paths, symlinks to devices) and retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import shutil\nfrom pathlib import Path\n\ndef room_to_extract(project_root: Path, archive: Path) -> bool:\n    need = archive.stat().st_size * 2\n    return shutil.disk_usage(project_root).free > need","typeGuard":null,"tryCatchPattern":"from specify_cli.extensions import ExtensionError\n\ntry:\n    install_from_url_cmd(project_root, url, speckit_version)\nexcept ExtensionError as e:\n    if 'Could not install extension from downloaded archive' in str(e):\n        cause = e.__cause__  # OSError errno tells: ENOSPC, EACCES, path length...","preventionTips":["Ensure .specify is writable and disk has ~2x archive size free","On Windows, enable long path support for deep .specify paths"],"tags":["extensions","filesystem","installation","archive"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}