问题现象
在 VS Code 通过 Remote SSH 打开远端 Markdown 文件时:
- 源文件可以正常编辑。
- 按
Ctrl+Shift+V能创建原生 Markdown 预览标签,但预览为白屏。 Developer: Reload Window无效。- Markdown 文件编码、语法和内容均正常。
- 最终出现明确错误:
text
Error loading webview provided by 'vscode.markdown-language-features':
Error: Could not register service worker: InvalidStateError:
Failed to register a ServiceWorker: The document is in an invalid state.
最终根因
本地 Windows VS Code 的 Webview Service Worker 状态或缓存损坏。
这不是远端 Markdown 文件、虚拟机或 Markdown 解析器的问题。即使文件位于远端,VS Code 原生 Markdown 预览的 webview 仍由本地 VS Code/Electron 客户端显示,并依赖本地 Service Worker。
显示原理
Remote SSH 下的原生 Markdown 预览链路如下:
Ctrl+Shift+V执行markdown.showPreview。- 远端
vscode.markdown-language-features读取并解析 Markdown。 - 生成的 HTML 传给本地 VS Code 客户端。
- 本地 Electron webview 注册 Service Worker 并显示内容。
因此:
- 无法创建预览标签:优先检查命令、语言模式和扩展激活。
- 能创建标签但白屏:优先检查本地 webview、Service Worker 和缓存。
- 报
Could not register service worker:直接处理本地 VS Code 缓存。
有效修复
先彻底关闭本地 Windows 上的所有 VS Code 窗口,然后在 Windows PowerShell 中执行:
powershell
taskkill /F /IM Code.exe 2>$null
$root = Join-Path $env:APPDATA 'Code'
$stamp = Get-Date -Format yyyyMMdd-HHmmss
@('Service Worker', 'WebStorage', 'Cache', 'CachedData', 'GPUCache') |
ForEach-Object {
$path = Join-Path $root $_
if (Test-Path $path) {
Move-Item $path "$path.bak-$stamp"
}
}
随后:
- 重新启动本地 VS Code。
- 重新连接 Remote SSH。
- 打开 Markdown 源文件。
- 按
Ctrl+Shift+V验证原生预览。
上述命令只是重命名缓存目录并保留备份,不会删除用户设置和扩展。
为什么 Reload 无效
Developer: Reload Window 只重载 VS Code 窗口和扩展宿主,不一定清除磁盘上的 Service Worker 注册信息、WebStorage 和 Chromium 缓存。损坏状态被重新加载后,预览仍会白屏。
同理,重启远端虚拟机通常无效,因为出错的状态位于本地 Windows:
text
%APPDATA%\Code\Service Worker
排查中发现的并发问题
本次还发现了几个独立问题,但它们不是最终白屏根因。
inotify 实例耗尽
虚拟机曾出现:
text
EMFILE: Too many open files
inotify_init() failed
原因是大量孤立的 dconf watch /system/proxy/ 进程耗尽了:
text
fs.inotify.max_user_instances = 128
清理孤立 watcher 后,VNC 内的 Office Viewer 恢复正常。这解释了 VNC 持续转圈,但不能解释 Remote SSH 原生预览的 Service Worker 错误。
扩展宿主内存异常
远端 Extension Host 曾多次接近 4 GB 后 OOM,并发现:
saoudrizwan.claude-dev@4.1.21持续产生PendingMigrationError。jebbs.plantuml@2.18.1注入markdown.markdownItPlugins,并在释放时抛出异常。
这些扩展可能导致远端宿主不稳定,值得单独升级或禁用,但清除本地 Service Worker 缓存才是本次原生预览恢复的关键。
原生预览与 Office Viewer 的区别
Ctrl+Shift+V:VS Code 内置的 Markdown Preview。Reopen Editor With... -> Markdown Editor:Office Viewer 提供的自定义编辑器。
两者使用不同的命令和编辑器实现。排查时必须先确认目标是原生预览还是 Office Viewer,否则容易把两个问题混在一起。
推荐排查顺序
- 确认源文件能打开,右下角语言模式为
Markdown。 - 用另一个简单 Markdown 文件测试,排除文件特定问题。
- 判断按
Ctrl+Shift+V后是"无反应"还是"有标签但白屏"。 - 打开
Developer: Open Webview Developer Tools查看 Console。 - 若出现 Service Worker 注册错误,关闭 VS Code 并清理本地 webview 缓存。
- 若没有 Service Worker 错误,再检查 Markdown 注入插件、Extension Host 日志和 GPU 加速。
结论
Remote SSH 中的 webview 是跨本地与远端协作的。远端负责文件和扩展逻辑,本地负责 Electron webview 显示。遇到"源文件正常、预览标签已创建、内容白屏"时,不要只检查远端虚拟机;应优先查看本地 Webview Developer Tools,并特别关注 Service Worker 注册状态。