{"record":{"id":"b41bc0b338f8176c","repo":"neoclide/coc.nvim","slug":"invalid-engines-field","errorCode":null,"errorMessage":"Invalid engines field","messagePattern":"Invalid engines field","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/extension/stat.ts","lineNumber":279,"sourceCode":"export function validExtensionFolder(folder: string, version: string): boolean {\n  let errors: string[] = []\n  let res = loadExtensionJson(folder, version, errors)\n  return res != null && errors.length == 0\n}\n\nfunction getEntryFile(main: string | undefined): string {\n  if (!main) return 'index.js'\n  if (!main.endsWith('.js')) return main + '.js'\n  return main\n}\n\nexport async function loadGlobalJsonAsync(folder: string, version: string): Promise<ExtensionJson> {\n  let jsonFile = path.join(folder, 'package.json')\n  let content = await readFile(jsonFile, 'utf8')\n  let packageJSON = JSON.parse(content) as ExtensionJson\n  let { engines } = packageJSON\n  let main = getEntryFile(packageJSON.main)\n  if (!engines || (typeof engines.coc !== 'string' && typeof engines.vscode !== 'string')) throw new Error('Invalid engines field')\n  let keys = Object.keys(engines)\n  if (keys.includes('coc') && !semver.satisfies(version, engines['coc'].replace(/^\\^/, '>='))) {\n    throw new Error(`coc.nvim version not match, required ${engines['coc']}`)\n  }\n  if (!engines.vscode && !fs.existsSync(path.join(folder, main))) {\n    throw new Error(`main file ${main} not found, you may need to build the project.`)\n  }\n  return packageJSON\n}\n\nexport function loadExtensionJson(folder: string, version: string, errors: string[]): ExtensionJson | undefined {\n  let jsonFile = path.join(folder, 'package.json')\n  if (!fs.existsSync(jsonFile)) {\n    errors.push(`package.json not found in ${folder}`)\n    return undefined\n  }\n  let packageJSON = loadJson(jsonFile) as ExtensionJson\n  let { name, engines } = packageJSON","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/extension/stat.ts#L261-L297","documentation":"Thrown by loadGlobalJsonAsync when an extension's package.json either has no `engines` field or lacks both `engines.coc` and `engines.vscode` strings. coc.nvim uses engines to verify compatibility, so a manifest without it is considered invalid.","triggerScenarios":"Installing/loading a global extension folder whose package.json has no engines field, or engines missing both coc and vscode entries; malformed hand-written package.json.","commonSituations":"Locally developed extensions missing engines; copied/vendored packages that are not coc extensions; npm packages accidentally installed into the extension root.","solutions":["Add `\"engines\": { \"coc\": \">= 0.0.80\" }` (or a vscode engine) to the extension's package.json","Ensure you are loading an actual coc extension, not an arbitrary npm package","Reinstall the extension from a proper release"],"exampleFix":"// before (package.json)\n{ \"name\": \"my-ext\", \"main\": \"lib/index.js\" }\n// after\n{ \"name\": \"my-ext\", \"main\": \"lib/index.js\", \"engines\": { \"coc\": \">=0.0.80\" } }","handlingStrategy":"validation","validationCode":"const pkg = JSON.parse(fs.readFileSync(path.join(folder, 'package.json'), 'utf8'));\nif (!pkg.engines || (typeof pkg.engines.coc !== 'string' && typeof pkg.engines.vscode !== 'string')) {\n  throw new Error('extension package.json lacks valid engines');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await installOrLoad(folder);\n} catch (e) {\n  if (e.message === 'Invalid engines field') {\n    console.error(`${folder} is not a valid coc extension (no engines.coc/vscode)`);\n  } else throw e;\n}","preventionTips":["Always include engines.coc in extension package.json","Only install extensions from trusted coc extension sources"],"tags":["extension","package-json","manifest-validation"],"backgroundTag":"invalid-engines-field","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}