{"record":{"id":"b741c3c61f0688a6","repo":"denoland/deno","slug":"unexpected-end-of-string-at","errorCode":null,"errorMessage":"Unexpected end of string at {}.","messagePattern":"Unexpected end of string at (.+?)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/lsp/path_to_regex.rs","lineNumber":86,"sourceCode":"  let mut chars = s.chars().peekable();\n  let mut index = 0_usize;\n\n  loop {\n    match chars.next() {\n      None => break,\n      Some(c) if c == '*' || c == '+' || c == '?' => {\n        tokens.push(LexToken {\n          token_type: TokenType::Modifier,\n          index,\n          value: c.to_string(),\n        });\n        index += 1;\n      }\n      Some('\\\\') => {\n        index += 1;\n        let value = chars\n          .next()\n          .ok_or_else(|| anyhow!(\"Unexpected end of string at {}.\", index))?;\n        tokens.push(LexToken {\n          token_type: TokenType::EscapedChar,\n          index,\n          value: value.to_string(),\n        });\n        index += 1;\n      }\n      Some('{') => {\n        tokens.push(LexToken {\n          token_type: TokenType::Open,\n          index,\n          value: '{'.to_string(),\n        });\n        index += 1;\n      }\n      Some('}') => {\n        tokens.push(LexToken {\n          token_type: TokenType::Close,","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/cli/lsp/path_to_regex.rs#L68-L104","documentation":"cli/lsp/path_to_regex.rs:86 is the lexer for the LSP's path-to-regex templates (registry schemas). On a backslash it consumes the next character as an EscapedChar token; if the input ends immediately after the '\\', there is no character to read and it errors with \"Unexpected end of string at {index}\". The index reported is the position of the (missing) escaped character.","triggerScenarios":"A registry schema string ending in a single backslash, e.g. \"/x/:pkg([a-z]+)\\\\\" or \"/static\\\\\"; also a URL-encoded %5C at the very end of a schema being lexed when the host is enabled for completions.","commonSituations":"Hand-escaping in JSON where one level of backslash was lost (\"\\\\\" collapsing to \"\\\"); trailing Windows-style path separators pasted into a schema; sed/regex transformations that leave a stray escape.","solutions":["Remove the trailing backslash from the schema string","Double-escape when it is intentional: JSON needs \"\\\\\\\\\" to yield a literal backslash inside the pattern","Run the schema through a path-to-regex checker before publishing the config"],"exampleFix":"// before\n{ \"schema\": \"/x/:pkg([a-z]+)\\\\\" }\n\n// after\n{ \"schema\": \"/x/:pkg([a-z]+)\" }","handlingStrategy":"validation","validationCode":"function endsWithDanglingEscape(s: string): boolean {\n  // count trailing backslashes; odd count means a dangling escape\n  let n = 0;\n  for (let i = s.length - 1; i >= 0 && s[i] === \"\\\\\"; i--) n++;\n  return n % 2 === 1;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never end a schema with a backslash; trailing separators are unnecessary","Escape backslashes in pairs at every layer (regex -> JSON)","Lint schemas with a path-to-regexp implementation before publishing"],"tags":["lsp","registry","schema","lexer"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}