neoclide/coc.nvim · error · Error
Invalid engines field
Error message
Invalid engines field
What it means
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.
Source
Thrown at src/extension/stat.ts:279
export function validExtensionFolder(folder: string, version: string): boolean {
let errors: string[] = []
let res = loadExtensionJson(folder, version, errors)
return res != null && errors.length == 0
}
function getEntryFile(main: string | undefined): string {
if (!main) return 'index.js'
if (!main.endsWith('.js')) return main + '.js'
return main
}
export async function loadGlobalJsonAsync(folder: string, version: string): Promise<ExtensionJson> {
let jsonFile = path.join(folder, 'package.json')
let content = await readFile(jsonFile, 'utf8')
let packageJSON = JSON.parse(content) as ExtensionJson
let { engines } = packageJSON
let main = getEntryFile(packageJSON.main)
if (!engines || (typeof engines.coc !== 'string' && typeof engines.vscode !== 'string')) throw new Error('Invalid engines field')
let keys = Object.keys(engines)
if (keys.includes('coc') && !semver.satisfies(version, engines['coc'].replace(/^\^/, '>='))) {
throw new Error(`coc.nvim version not match, required ${engines['coc']}`)
}
if (!engines.vscode && !fs.existsSync(path.join(folder, main))) {
throw new Error(`main file ${main} not found, you may need to build the project.`)
}
return packageJSON
}
export function loadExtensionJson(folder: string, version: string, errors: string[]): ExtensionJson | undefined {
let jsonFile = path.join(folder, 'package.json')
if (!fs.existsSync(jsonFile)) {
errors.push(`package.json not found in ${folder}`)
return undefined
}
let packageJSON = loadJson(jsonFile) as ExtensionJson
let { name, engines } = packageJSONView on GitHub (pinned to 50e974d969)
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
Example fix
// before (package.json)
{ "name": "my-ext", "main": "lib/index.js" }
// after
{ "name": "my-ext", "main": "lib/index.js", "engines": { "coc": ">=0.0.80" } } Defensive patterns
Strategy: validation
Validate before calling
const pkg = JSON.parse(fs.readFileSync(path.join(folder, 'package.json'), 'utf8'));
if (!pkg.engines || (typeof pkg.engines.coc !== 'string' && typeof pkg.engines.vscode !== 'string')) {
throw new Error('extension package.json lacks valid engines');
} Try / catch
try {
await installOrLoad(folder);
} catch (e) {
if (e.message === 'Invalid engines field') {
console.error(`${folder} is not a valid coc extension (no engines.coc/vscode)`);
} else throw e;
} Prevention
- Always include engines.coc in extension package.json
- Only install extensions from trusted coc extension sources
When it happens
Trigger: 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.
Common situations: Locally developed extensions missing engines; copied/vendored packages that are not coc extensions; npm packages accidentally installed into the extension root.
Related errors
- Unable to load extension at ${extensionRoot}, missing packag
- Unable to load extension at ${filepath}
- extension ${name} is disabled
- coc.nvim version not match, required ${engines['coc']}
- main file ${main} not found, you may need to build the proje
AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31).
Data as JSON: /api/errors/b41bc0b338f8176c.
Report an issue: GitHub.