{"record":{"id":"4ae3aeb20a75f505","repo":"neoclide/coc.nvim","slug":"invalid-access-to-exports-extension-id-not-a","errorCode":null,"errorMessage":"Invalid access to exports, extension \"${id}\" not activated","messagePattern":"Invalid access to exports, extension \"(.+?)\" not activated","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/extension/manager.ts","lineNumber":523,"sourceCode":"          } catch (e) {\n            logger.error(`Error on active extension ${id}:`, e)\n            reject(e as Error)\n          }\n        })\n        return result\n      },\n      id,\n      packageJSON,\n      extensionPath,\n      extensionUri: URI.file(extensionPath),\n      get isActive() {\n        return isActive\n      },\n      get module() {\n        return ext\n      },\n      get exports() {\n        if (!isActive) throw new Error(`Invalid access to exports, extension \"${id}\" not activated`)\n        return exports\n      }\n    }\n    Object.freeze(extension)\n    this.extensions.set(id, {\n      id,\n      type: extensionType,\n      isLocal: extensionType == ExtensionType.Local,\n      extension,\n      directory: root,\n      filepath: filename,\n      events: getEvents(packageJSON.activationEvents),\n      deactivate: async () => {\n        if (!isActive) return\n        isActive = false\n        result = undefined\n        exports = undefined\n        disposeExtension(id)","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/extension/manager.ts#L505-L541","documentation":"The Extension object exposed by ExtensionManager defines a getter for `exports` that throws `Invalid access to exports, extension \"<id>\" not activated` whenever the extension has not finished activating. This guards the VS Code-like contract that extension.exports is only meaningful after activate() resolves, preventing callers from reading partial/undefined exports.","triggerScenarios":"Synchronously accessing extension.exports right after getExtension()/onDidExtension activation-event registration but before activation completes; accessing exports inside an activation handler before await activate() resolves; any code path reading exports of a lazily-activated extension.","commonSituations":"Plugin code doing `const api = extensions.getExtension('coc-x').exports` without awaiting activation; using exports in an onActivation callback that runs before the extension's own activate finishes.","solutions":["Check extension.isActive before touching exports, and await extension.activate() when it is not active","Use ExtensionManager.call(id, method, args), which activates automatically, instead of reading exports directly","Subscribe to the extension activation event and access exports only in the callback","If exports should exist immediately, change the extension to an eagerly activated type"],"exampleFix":"// before\nconst ext = extensions.getExtension('coc-x')\nconst api = ext.exports // throws if not activated\n// after\nconst ext = extensions.getExtension('coc-x')\nif (!ext.isActive) await ext.activate()\nconst api = ext.exports","handlingStrategy":"try-catch","validationCode":"const ext = extensions.getExtension(id)\nif (!ext.isActive) await ext.activate() // ensures exports getter is safe","typeGuard":"function activatedExports<T>(ext: { isActive: boolean; activate(): Promise<T>; exports: T }): T | undefined {\n  return ext.isActive ? ext.exports : undefined\n}","tryCatchPattern":"let api\ntry {\n  api = ext.exports\n} catch (e) {\n  if (/Invalid access to exports/.test(e.message)) {\n    await ext.activate()\n    api = ext.exports\n  } else throw e\n}","preventionTips":["Always await activate() before reading exports","Access exports only inside activation callbacks/events","Prefer manager.call() which handles lazy activation","Never cache exports references across deactivation cycles"],"tags":["extension-api","activation","lazy-init"],"backgroundTag":"exports-not-activated","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}