Ginexys
Postmortem: Shipping Five VS Code Extensions to Marketplace in One Session
TLDR
Shipping our five-extension suite (ginexys-core, ginexys-tafne, ginexys-pdf, ginexys-schema, ginexys-pack) to the VS Code Marketplace was planned as a 30-minute release task. It turned into a 5-hour engineering session due to monorepo symlink leaks (55MB artifacts), runtime cross-extension require() crashes, and global package name collisions.
| Publishing Incident | Root Cause | Engineering Remediation | Final Resolution Time |
|---|---|---|---|
| 55MB Bundle Bloat | vsce package followed pnpm workspace symlinks | Added ../<sibling>/* & ../../ to .vscodeignore | 1 hour |
Post-Install require() Crash | tafne imported core via node_modules symlink | Refactored to vscode.extensions.getExtension().exports | 2.5 hours |
| Global Name Rejection | name: "core" was taken globally on Marketplace | Renamed package to ginexys-core & refactored references | 1.5 hours |
Extension development hosts hide runtime packaging differences
Prior to release day, our extension suite had been thoroughly tested inside VS Code's Extension Development Host (F5). All five packages compiled cleanly via pnpm -r compile, inter-extension communication worked smoothly, and webviews rendered flawlessly.
However, compilation proving internal consistency is not the same as packaging proving external artifact consistency. F5 development relies on local workspace symlinks; the Marketplace relies on isolated, unpacked .vsix archives.
Sequenced release-day failures block initial deployment
We hit three sequential failure modes during release:
Release Engineer vsce package tool Marketplace Registry
| | |
|--- 1. vsce package ----------->| |
|<-- 2. 55MB Bloated Bundle ----| |
|--- 3. Fix .vscodeignore (216KB) |
| |
|--- 4. Test production install ----------------------------->|
|<-- 5. Runtime Error (Cannot find module 'core/...') --------|
|--- 6. Fix: Refactor to activate-exports API |
| |
|--- 7. vsce publish "core" --------------------------------->|
|<-- 8. HTTP 400 (Name 'core' already taken globally) --------|
|--- 9. Rename to ginexys-core & publish successfully ------->|
1. Monorepo artifact bloat
The initialvsce package in packages/core produced a 55 MB package containing all sibling extension directories, root configuration files, and build scripts.
Fix: Configured explicit relative ignore rules (../core/, ../../) in .vscodeignore, bringing the package size down to 216 KB.
2. Runtime extension sandboxing violations
In production, VS Code installs each extension into an isolated sandboxed directory. The compiledTafneEditorProvider.js contained require("core/webview/html-rewriter"), which threw Module not found in production because node_modules symlinks do not exist post-install.
- Fix: Converted
core'sactivate()function to return a public API object and updated satellite extensions to consume it viavscode.extensions.getExtension('ginexys.ginexys-core').exports.
3. Global name collisions
Marketplace rejectedname: "core" because the name property is globally unique across all publishers in the registry.
- Fix: Renamed the package to
ginexys-coreand updated 11 reference call sites across the codebase.
Decoupled monorepos support scalable multi-extension suites
Once the deployment artifacts were properly structured, the core engine logic executed flawlessly:
- The webview HTML rewriter accurately injected nonces and local media roots.
- The authentication provider securely managed OAuth keys across extensions.
- The IPC router coordinated multi-tool commands.
Rule of thumb: Test your deployment packaging workflow (vsce package) on day one of development. Never wait until release day to discover monorepo symlink leaks or cross-package runtime resolution failures.
Read this post in the full Engineering Journal →