{"record":{"id":"2065b5f510cdf1bc","repo":"neoclide/coc.nvim","slug":"feature-param-could-only-starts-with-nvim-and-patc","errorCode":null,"errorMessage":"Feature param could only starts with nvim and patch","messagePattern":"Feature param could only starts with nvim and patch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/core/funcs.ts","lineNumber":35,"sourceCode":"const namespaceMap: Map<string, number> = new Map()\nconst mutex: Mutex = new Mutex()\n\nexport interface PartialEnv {\n  isVim: boolean\n  version: string\n}\n\n/**\n * Like vim's has(), but for version check only.\n * Check patch on neovim and check nvim on vim would return false.\n *\n * For example:\n * - has('nvim-0.6.0')\n * - has('patch-7.4.248')\n */\nexport function has(env: PartialEnv, feature: string): boolean {\n  if (!feature.startsWith('nvim-') && !feature.startsWith('patch-')) {\n    throw new Error('Feature param could only starts with nvim and patch')\n  }\n  if (!env.isVim && feature.startsWith('patch-')) {\n    return false\n  }\n  if (env.isVim && feature.startsWith('nvim-')) {\n    return false\n  }\n  if (env.isVim) {\n    let [_, major, minor, patch] = env.version.match(/^(\\d)(\\d{2})(\\d+)$/)\n    let version = `${major}.${parseInt(minor, 10)}.${parseInt(patch, 10)}`\n    return semver.gte(version, convertVersion(feature.slice(6)))\n  }\n  return semver.gte(env.version, feature.slice(5))\n}\n\n// convert to valid semver version 9.0.0138 to 9.0.138\nfunction convertVersion(version: string): string {\n  let parts = version.split('.')","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/core/funcs.ts#L17-L53","documentation":"The env feature check helper only supports editor-version features of the form 'nvim-x.y.z' or 'patch-x.y.z'. Any other feature string (e.g. 'python3', 'clipboard') is rejected as a programming error rather than silently returning false.","triggerScenarios":"Calling workspace.hasFeature / env has('python3') or other arbitrary vim has() features through coc's has() helper.","commonSituations":"Porting vimscript logic where has() accepts any feature; extension authors checking non-version capabilities with the wrong API.","solutions":["Only pass 'nvim-<version>' or 'patch-<version>' strings to this API","Use nvim.call('has', 'python3') or the appropriate coc API for non-version features","Check the feature string for typos/missing prefix"],"exampleFix":"// before\nhas(env, 'python3')\n// after\nif (feature.startsWith('nvim-') || feature.startsWith('patch-')) has(env, feature)\nelse env.nvim.call('has', feature)","handlingStrategy":"validation","validationCode":"const supported = f => typeof f === 'string' && (f.startsWith('nvim-') || f.startsWith('patch-'))\nif (!supported(feature)) return null // use nvim.call('has', feature) instead","typeGuard":"const isVersionFeature = (f): f is `nvim-${string}` | `patch-${string}` =>\n  typeof f === 'string' && (f.startsWith('nvim-') || f.startsWith('patch-'))","tryCatchPattern":null,"preventionTips":["Only use this API for nvim-/patch- version checks","Route other has() features through nvim.call('has', ...)","Review ported vimscript has() calls when migrating extensions"],"tags":["validation","api-misuse","editor-feature"],"backgroundTag":"invalid-argument","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}