neoclide/coc.nvim · error
`tokenModifier` is not in the provided legend
Error message
`tokenModifier` is not in the provided legend
What it means
Each string token modifier must exist in the legend's tokenModifiers array so it can be converted to a bitmask. If any modifier string in the modifiers array is unknown to the legend, the builder throws this error.
Source
Thrown at src/model/semanticTokensBuilder.ts:95
private _push(range: Range, tokenType: string, tokenModifiers?: string[]): void {
if (!this._hasLegend) {
throw new Error('Legend must be provided in constructor')
}
if (range.start.line !== range.end.line) {
throw new Error('`range` cannot span multiple lines')
}
if (!this._tokenTypeStrToInt.has(tokenType)) {
throw new Error('`tokenType` is not in the provided legend')
}
const line = range.start.line
const char = range.start.character
const length = range.end.character - range.start.character
const nTokenType = this._tokenTypeStrToInt.get(tokenType)!
let nTokenModifiers = 0
if (tokenModifiers) {
for (const tokenModifier of tokenModifiers) {
if (!this._tokenModifierStrToInt.has(tokenModifier)) {
throw new Error('`tokenModifier` is not in the provided legend')
}
const nTokenModifier = this._tokenModifierStrToInt.get(tokenModifier)!
nTokenModifiers |= (1 << nTokenModifier) >>> 0
}
}
this._pushEncoded(line, char, length, nTokenType, nTokenModifiers)
}
private _pushEncoded(line: number, char: number, length: number, tokenType: number, tokenModifiers: number): void {
if (this._dataIsSortedAndDeltaEncoded && (line < this._prevLine || (line === this._prevLine && char < this._prevChar))) {
// push calls were ordered and are no longer ordered
this._dataIsSortedAndDeltaEncoded = false
// Remove delta encoding from data
const tokenCount = (this._data.length / 5) | 0
let prevLine = 0
let prevChar = 0
for (let i = 0; i < tokenCount; i++) {View on GitHub (pinned to 50e974d969)
Solutions
- Include all server-declared modifiers in the tokenModifiers legend array
- Filter unknown modifiers before pushing: modifiers.filter(m => legend.tokenModifiers.includes(m))
- Sync the legend from the server's SemanticTokensLegend rather than hand-writing it
Example fix
// before builder.push(range, 'function', ['static']) // 'static' not in legend // after const known = ['static'].filter(m => legend.tokenModifiers.includes(m)) builder.push(range, 'function', known)
Defensive patterns
Strategy: validation
Validate before calling
const safeModifiers = modifiers.filter(m => legend.tokenModifiers.includes(m))
Type guard
function areKnownModifiers(ms: string[], legend: SemanticTokensLegend): boolean {
return ms.every(m => legend.tokenModifiers.includes(m))
} Try / catch
try {
builder.push(range, tokenType, modifiers)
} catch (e) {
if (e.message.includes('tokenModifier` is not in the provided legend')) {
console.warn('Unknown token modifiers dropped', modifiers)
}
} Prevention
- Keep the client legend in sync with the server's SemanticTokensLegend
- Filter unknown modifiers instead of passing them raw
- Log unknown modifiers once to detect legend drift early
When it happens
Trigger: Calling push(range, 'keyword', ['static']) where 'static' is not in the tokenModifiers array given to the constructor; a server emitting a modifier absent from the client-built legend.
Common situations: Client legend built from an older spec while the server added new modifiers (e.g. 'defaultLibrary'); typos in modifier names; forgetting modifiers entirely in the legend object.
Related errors
- `tokenType` is not in the provided legend
- Illegal argument
- Legend must be provided in constructor
- Command: ${command} not found
- name and doComplete required for createSource
AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31).
Data as JSON: /api/errors/3939fca39ea4bc0f.
Report an issue: GitHub.