SeleniumHQ/selenium · error · OSError
Add-on path is neither an XPI nor a directory: {addon_path}
Error message
Add-on path is neither an XPI nor a directory: {addon_path} What it means
Raised when the addon_path exists but is neither a valid ZIP/XPI file (zipfile.is_zipfile returns False) nor a directory (os.path.isdir returns False). This catches cases like passing a regular file, a broken archive, or a symlink to a non-directory.
Source
Thrown at py/selenium/webdriver/firefox/firefox_profile.py:293
raise OSError(f"Add-on path does not exist: {addon_path}")
try:
if zipfile.is_zipfile(addon_path):
with zipfile.ZipFile(addon_path, "r") as compressed_file:
if "manifest.json" in compressed_file.namelist():
return parse_manifest_json(compressed_file.read("manifest.json"))
manifest = compressed_file.read("install.rdf")
elif os.path.isdir(addon_path):
manifest_json_filename = os.path.join(addon_path, "manifest.json")
if os.path.exists(manifest_json_filename):
with open(manifest_json_filename, encoding="utf-8") as f:
return parse_manifest_json(f.read())
with open(os.path.join(addon_path, "install.rdf"), encoding="utf-8") as f:
manifest = f.read()
else:
raise OSError(f"Add-on path is neither an XPI nor a directory: {addon_path}")
except (OSError, KeyError) as e:
raise AddonFormatError(str(e), sys.exc_info()[2])
try:
doc = minidom.parseString(manifest)
# Get the namespaces abbreviations
em = get_namespace_id(doc, "http://www.mozilla.org/2004/em-rdf#")
rdf = get_namespace_id(doc, "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
description = doc.getElementsByTagName(rdf + "Description").item(0)
if not description:
description = doc.getElementsByTagName("Description").item(0)
for node in description.childNodes:
# Remove the namespace prefix from the tag for comparison
entry = node.nodeName.replace(em, "")
if entry in details:
details.update({entry: get_text(node)})View on GitHub (pinned to aa36b38e69)
Solutions
- Confirm the file is a valid zip: run zipfile.is_zipfile(addon_path) to check before calling
- Re-download the .xpi if it may be corrupted or truncated
- If installing from a directory, ensure the path is a directory and not a single file
Example fix
// before
profile.add_extension('/downloads/plugin') # 'plugin' is a plain file
// after
import zipfile
if zipfile.is_zipfile('/downloads/plugin.xpi'):
profile.add_extension('/downloads/plugin.xpi')
else:
raise ValueError('Not a valid XPI archive') Defensive patterns
Strategy: validation
Validate before calling
import os, zipfile
addon_path = '/path/to/addon'
if not (zipfile.is_zipfile(addon_path) or os.path.isdir(addon_path)):
raise ValueError(f'Path must be an XPI or directory: {addon_path}')
profile.add_extension(addon_path) Type guard
import os, zipfile
def is_valid_addon_path(p: str) -> bool:
return os.path.exists(p) and (zipfile.is_zipfile(p) or os.path.isdir(p)) Try / catch
from selenium.common.exceptions import AddonFormatError
try:
profile.add_extension(addon_path)
except (OSError, AddonFormatError) as e:
print(f'Invalid addon: {e}')
# re-download or use alternate path Prevention
- Verify the file is a valid zip with zipfile.is_zipfile before passing
- Ensure the path points to a directory or .xpi, not a plain file
- Re-download corrupted .xpi files
When it happens
Trigger: Passing a path to a plain file (e.g., a .txt or .json), a corrupted/partially-downloaded .xpi that is no longer a valid zip, or a path that points to a named pipe or special file.
Common situations: Corrupted downloads where the .xpi is incomplete or contains HTML error content. Accidentally pointing at a README or metadata file instead of the actual addon package.
Related errors
- Add-on path does not exist: {addon_path}
- {str(e)}
- Add-on id could not be found.
- Couldn't find manifest.json in ${extension}
- Could not find add-on ID for ${extension}
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/872b3d34c03cd12e.
Report an issue: GitHub.