neoclide/coc.nvim · error

pattern \z not supported

Error message

pattern \z not supported

What it means

convertRegex translates Python (VS Code snippet) regex syntax into JavaScript regex for snippet transforms. Python's \z (and \Z semantics) have no JS equivalent, so the function rejects the pattern up front rather than producing wrong replacements. Called when parsing ${var/regex/repl/} transforms.

Source

Thrown at src/snippets/util.ts:72

  // options from ultisnips context
  noExpand?: boolean
  [key: string]: boolean | number | string | undefined
}

const stringStartRe = /\\A/
const conditionRe = /\(\?\(\w+\).+\|/
const commentRe = /\(\?#.*?\)/
const namedCaptureRe = /\(\?P<\w+>.*?\)/
const namedReferenceRe = /\(\?P=(\w+)\)/
const regex = new RegExp(`${commentRe.source}|${stringStartRe.source}|${namedCaptureRe.source}|${namedReferenceRe.source}`, 'g')

/**
 * Convert python regex to javascript regex,
 * throw error when unsupported pattern found
 */
export function convertRegex(str: string): string {
  if (str.indexOf('\\z') !== -1) {
    throw new Error('pattern \\z not supported')
  }
  if (str.indexOf('(?s)') !== -1) {
    throw new Error('pattern (?s) not supported')
  }
  if (str.indexOf('(?x)') !== -1) {
    throw new Error('pattern (?x) not supported')
  }
  if (str.indexOf('\n') !== -1) {
    throw new Error('pattern \\n not supported')
  }
  if (conditionRe.test(str)) {
    throw new Error('pattern (?id/name)yes-pattern|no-pattern not supported')
  }
  return str.replace(regex, (match, p1) => {
    if (match.startsWith('(?#')) return ''
    if (match.startsWith('(?P<')) return '(?' + match.slice(3)
    if (match.startsWith('(?P=')) return `\\k<${p1}>`
    // if (match == '\\A') return '^'

View on GitHub (pinned to 50e974d969)

Solutions

  1. Remove the \z or \Z escape from the transform regex.
  2. Rewrite the transform using standard JS-compatible anchors/matches.
  3. Drop the transform and use a plain placeholder if the regex is unnecessary.
  4. Ask the snippet author for a portable variant.

Example fix

// before
'${1/(\\z)/x/}'
// after
'${1/(z)/x/}'
Defensive patterns

Strategy: validation

Validate before calling

function regexIsPortable(pattern: string): boolean {
  return !pattern.includes('\\z')
}

Type guard

null

Try / catch

try {
  let js = convertRegex(pattern)
} catch (e) {
  if (String(e.message).includes('\\z')) pattern = pattern.replace(/\\[zZ]/g, '')
}

Prevention

When it happens

Trigger: A snippet transform whose regex contains the literal \z, e.g. ${1/(\z)/x/}.

Common situations: Snippets copied from other editors or documentation that use Python-specific regex escapes.

Related errors


AI-assisted analysis of neoclide/coc.nvim@50e974d969 (2026-08-31). Data as JSON: /api/errors/d10eb84cb6b0d151. Report an issue: GitHub.