{"record":{"id":"5b9d8881f6d67886","repo":"SeleniumHQ/selenium","slug":"couldn-t-find-manifest-json-in-extension","errorCode":null,"errorMessage":"Couldn't find manifest.json in ${extension}","messagePattern":"Couldn't find manifest\\.json in (.+?)","errorType":"validation","errorClass":"AddonFormatError","httpStatus":null,"severity":"error","filePath":"javascript/selenium-webdriver/firefox.js","lineNumber":155,"sourceCode":"  }\n}\n\n/**\n * Installs an extension to the given directory.\n * @param {string} extension Path to the xpi extension file to install.\n * @param {string} dir Path to the directory to install the extension in.\n * @return {!Promise<string>} A promise for the add-on ID once\n *     installed.\n */\nasync function installExtension(extension, dir) {\n  const ext = extension.slice(-4)\n  if (ext !== '.xpi' && ext !== '.zip') {\n    throw Error('File name does not end in \".zip\" or \".xpi\": ' + ext)\n  }\n\n  let archive = await zip.load(extension)\n  if (!archive.has('manifest.json')) {\n    throw new AddonFormatError(`Couldn't find manifest.json in ${extension}`)\n  }\n\n  let buf = await archive.getFile('manifest.json')\n  let parsedJSON = JSON.parse(buf.toString('utf8'))\n\n  let { browser_specific_settings } =\n    /** @type {{browser_specific_settings:{gecko:{id:string}}}} */\n    parsedJSON\n\n  if (browser_specific_settings && browser_specific_settings.gecko) {\n    /* browser_specific_settings is an alternative to applications\n     * It is meant to facilitate cross-browser plugins since Firefox48\n     * see https://bugzilla.mozilla.org/show_bug.cgi?id=1262005\n     */\n    parsedJSON.applications = browser_specific_settings\n  }\n\n  let { applications } =","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/javascript/selenium-webdriver/firefox.js#L137-L173","documentation":"Thrown by installExtension() in firefox.js when the provided .xpi or .zip archive does not contain a manifest.json entry at its root. Firefox extensions are required to include this manifest. The archive is loaded via zip.load() and checked with archive.has('manifest.json').","triggerScenarios":"Passing a zip/xpi that is not a Firefox extension (e.g., a Chrome .crx renamed, a generic zip). The archive has manifest.json nested in a subdirectory rather than at root. A corrupted or incomplete archive.","commonSituations":"Trying to install a Chrome extension in Firefox; extension build pipeline outputting the wrong structure; selecting the wrong file from a build directory; manifest.json placed in a subfolder during packaging.","solutions":["Unzip the archive and confirm manifest.json is at the root level.","Rebuild the extension so manifest.json sits at the archive root.","Use a valid Firefox .xpi from AMO or your build tool (web-ext).","Ensure you are passing a Firefox extension, not a Chrome extension."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const AdmZip = require('adm-zip') // or equivalent\nasync function validateExtensionArchive(extensionPath) {\n  const archive = await zip.load(extensionPath)\n  if (!archive.has('manifest.json')) {\n    throw new Error(`Archive ${extensionPath} has no root manifest.json`)\n  }\n  return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Inspect the archive contents (unzip -l) before installing to confirm root-level manifest.json.","Use web-ext or a proper Firefox build tool to produce valid .xpi files.","Do not pass Chrome extensions (.crx) to Firefox installExtension().","Ensure manifest.json is at the archive root, not in a subdirectory."],"tags":["firefox","extension","validation","addon","archive"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}