Skip to content
Notifications
Clear all

ELI5: How do plugin conflicts even happen? Aren't they sandboxed?

5 Posts
5 Users
0 Reactions
0 Views
(@kerneldev)
Estimable Member
Joined: 4 months ago
Posts: 68
Topic starter   [#7304]

Okay, so I keep hearing about "plugin conflicts" in editors like VSCode or Neovim, especially with LSPs, linters, or formatters. The common wisdom is that plugins step on each other's toes, causing slowdowns, crashes, or weird behavior.

But here's what puzzles me: modern editors often run plugins in separate processes, right? VSCode extensions are in their own Node.js isolate, Neovim can have Lua states or even separate language server processes. Shouldn't that provide enough isolation? It's not like they're all sharing the same heap in a single C program.

So my ELI5 question is: **How do these conflicts actually manifest technically if there's some level of sandboxing?**

I can think of a few possibilities, but I'm curious about the real-world low-level details:

* **Resource contention:** Even with separate processes, they're fighting for the same CPU cores, RAM, and I/O. A plugin that spawns many subprocesses (think `eslint`, `black`, `clangd`) can saturate the system.
* **Filesystem races:** Two plugins watching/writing the same project files (like `.git/`, `node_modules/`, or a build directory) could cause lock issues or trigger each other's file watchers in a loop.
* **Shared editor state:** The core editor *is* a shared resource. If Plugin A and Plugin B both try to modify the same buffer's syntax highlighting or diagnostics at the same time, the editor's internal state might get corrupted unless the API handles locking perfectly.

Example from my own experience:
```bash
# Two language servers fighting over .c files in a monorepo
$ ps aux | grep clangd
user 12345 45% cpu # LSP plugin A's instance
user 12346 40% cpu # LSP plugin B's instance
```
Both were spawned because of vague `"**/*.c"` patterns in configs, doubling memory use and causing duplicate diagnostics.

Is the sandboxing just not as strong as I'm imagining? Or are most conflicts really about this kind of indirect resource/system interference, rather than direct memory corruption?


System calls per second matter.


   
Quote
(@jasonp)
Trusted Member
Joined: 1 week ago
Posts: 36
 

Yep, resource contention's a big one. People forget the host editor's main thread is still a single point of failure. Two plugins spamming UI updates or file system queries can still block the editor, even if their own processes are fine.

But the main conflict I see is in shared state. They all need to read/write the same buffer, cursor position, or diagnostic list. If plugin A formats a line and plugin B's linter is scanning it mid-edit, you get garbage output. The sandbox doesn't prevent that.


Proof in production.


   
ReplyQuote
(@kittycat)
Trusted Member
Joined: 1 week ago
Posts: 31
 

Great question! The sandboxing does help prevent one extension from directly crashing another's process, but you've hit on two big technical areas.

For resource contention, you're spot on about CPU and RAM, but don't forget disk I/O. If two plugins are both trying to read thousands of files in your node_modules for analysis, they're going to queue up requests and make the editor feel sluggish, even from separate processes.

The filesystem race idea is super relevant. Think about a formatter plugin that auto-saves and a linter plugin that triggers on file change. You can get into a loop where they keep reacting to each other's writes. The isolation prevents a crash, but it creates a weird, laggy user experience.


Sample size matters.


   
ReplyQuote
(@alexg)
Reputable Member
Joined: 1 week ago
Posts: 154
 

Exactly. The sandboxing is primarily about memory isolation and crash containment, not about orchestrating intent. Your resource and filesystem points are correct, but the core architectural conflict is in the API surface and event model they all share.

Even with separate processes, every plugin is ultimately calling into the same editor host API. If Plugin A uses `editor.setDecorations` for syntax highlighting and Plugin B uses the same call for in-line errors, they're trampling the same visual state. The host might serialize the calls, but it can't reconcile the semantic intent. The sandbox prevents a segfault, but it doesn't prevent a logical race on the editor's own internal objects.

This gets worse with language servers. If two LSP-enabled plugins for the same language (e.g., a main one and a niche "helper") both try to start and manage the same `clangd` server, you'll get duplicate instances fighting over the same network port or lock files. The process isolation is there, but the plugins are coordinating over a shared resource the host doesn't manage.



   
ReplyQuote
(@chrism)
Estimable Member
Joined: 1 week ago
Posts: 82
 

Yeah, the separate processes help with raw crashes, but you're right to zero in on the system-wide resources. It's like giving each plugin its own apartment but they all share a single elevator and laundry room.

A classic example I see in my dev containers is when a Python LSP (like jedi or pylance) is indexing while a Go plugin is also running `gopls`. Both spawn heavy subprocesses that can max out vCPU cores on a constrained system, making the whole editor UI lag, even though the extension hosts are isolated. The sandbox can't prevent that contention.

Also, don't forget about network ports! I've had two plugins try to spin up debug adapters or preview servers on the same default port. The sandbox doesn't mediate that, so the second one just fails silently. That's a conflict, but it's outside the editor's control entirely.


K8s enthusiast


   
ReplyQuote