# Reported issues for MagicTeX

Pod holds 16 of 32 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [MagicTeX](/mcp/magictex).

## Most discussed

### System-TeX backend: a TeX installed after startup is invisible, and when latexmk cannot run we report the wrong reason

Found by testing a real IEEEtran paper on Windows against the published 0.1.9,
rather than by review. Three defects, and they chain: the first makes the second
reachable, and the third is why a user walks into them at all.

## 1. A TeX installed after the server started is invisible, forever

`src/engine/systemTex.ts`:

```ts
let cached: 'latexmk' | null | undefined;
export async function hasSystemTex(): Promise<boolean> {
  if (cached !== undefined) return cached !== null;   // one null, always

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/89) · 2026-07-27 · closed · 2 comments

### Ctrl+S sometimes reports a compile success that did not happen, and the preview can stay on the previous version

Reported from real use on a 15-page IEEE paper, system backend:

> 有时候不知道为什么需要刷新页面才能看到最新更新,CTRL S 有时候报假的编译成功
>
> (sometimes the page has to be reloaded before the update shows; Ctrl+S
> sometimes reports a compile success that did not happen)

Both are intermittent, so what follows separates what is verified from what is
not. A tool for writing papers reporting a success that did not happen is the
worst failure it has, so this is filed even though the mechanism is not yet
pinned.

## Verified: w

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/98) · 2026-07-27 · closed · 1 comment

### MAGICTEX_ASSETS_DIR with forward slashes 403s every engine asset on Windows, and the same guard's containment check has no separator boundary

Found while verifying the 0.1.9 artifact from npm — not introduced by it, and not
caught by any test because every test and smoke lets the asset directory be
discovered rather than set.

`serveFrom` in `src/preview/previewServer.ts`:

```ts
const filePath = normalize(join(root, rel));
if (!filePath.startsWith(root)) { res.writeHead(403).end('forbidden'); return; }
```

Two defects in those two lines.

## 1. `MAGICTEX_ASSETS_DIR` with forward slashes 403s every engine asset

`join`/`normalize` re

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/84) · 2026-07-26 · closed · 1 comment

### Harden the local preview server (details held until 0.1.9 is published)

Found by `/code-review ultra` over the whole of `src/`, `ui/src/` and `bin/`.

**Details are held back until 0.1.9 is published** — 0.1.8 is the version on npm
and does not have these fixes. A full write-up will be added to this issue after
the release. What follows is enough to review the change without being a recipe.

## The shape of it

The preview server binds `127.0.0.1`. That keeps other machines out, and says
nothing about the user's own browser: localhost is reachable from every origin 

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/70) · 2026-07-26 · closed · 1 comment

### Docs are out of step with the code: a startup check that doesn't exist, a wrong download size, and translations missing half their sections

An audit of the docs against the code turned up three gaps. The first is a
promise the code never kept; the other two are wrong or missing facts a reader
would act on.

## 1. The README claims a startup check that does not exist

> Node 20.19+ (the floor `chokidar` and `playwright` actually need; **the server
> checks at startup and says so**)

```console
$ grep -rn "process.version" src/
$
```

Nothing reads it. `engines` in `package.json` only makes **npm** warn, and the
documented install lin

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/59) · 2026-07-26 · closed · 1 comment

### Two servers compiling one project corrupt the build, and it never recovers on its own

Two MagicTeX servers compiling the same project corrupt each other's build, and
the failure that comes out of it points nowhere near the cause.

Reproduced by accident and in full: a second process ran `render_preview` against
a project a running workspace was already compiling. Both write
`.latex-preview/build/` and, with shell-escape on, the same Inkscape output under
`svg-inkscape/`. One of them read a half-written intermediate:

```
xdvipdfmx:warning: >> Reading special command stopped aroun

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/95) · 2026-07-27 · open · 0 comments

### The new system-TeX guidance claims a local run that never happened, and blames it for the wrong failure

The guidance added in #90 asserts two things it has not measured — the same
mistake #89 was filed about, made one level down inside its own fix. Both are in
`main` now, and 0.1.10's version bump is already there too, so they would ship.

Found by running the merged code against a real IEEEtran paper rather than by
reading it.

**It reports a run that never happened.** With `backend: "wasm"` forced, nothing
is invoked locally, but the message says:

> Your local TeX ran and did not get through th

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/91) · 2026-07-27 · closed · 0 comments

### Releasing is four steps kept only as habit — 0.1.9 shipped with two of them missed

Releasing this project takes four steps, and they exist only as habit. 0.1.9
shipped with two of them missed, by me, and nothing anywhere would have caught it:

| step | 0.1.8 | 0.1.9 |
| --- | --- | --- |
| `RELEASE-x.y.z.md` committed | ✅ | ❌ |
| `npm publish` | ✅ | ✅ |
| GitHub release (body = that file) | ✅ | ✅ |
| `mcp-publisher publish` (server.json) | ✅ | ❌ |

The MCP registry still lists **0.1.8** as latest:

```
0.1.2  0.1.3  0.1.4  0.1.5  0.1.6  0.1.7  0.1.8 <-- isLatest
```

so anyone

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/87) · 2026-07-27 · closed · 0 comments

## Most recent

### First-run asset download breaks on Windows when the user's home path contains a space

Found by the full-codebase review before 0.1.9. This one breaks the **first
compile on a new machine**, for a large share of Windows users.

`src/engine/assets.ts` launches the one-time 480 MB asset download like this:

```ts
spawn('npx', ['texlyre-busytex', 'download-assets', dest], {
  shell: process.platform === 'win32', // npx.cmd on Windows
});
```

With `shell: true`, Node does not hand the child an argv. It joins the arguments
with spaces into a single command line and passes that to the 

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/81) · 2026-07-26 · closed · 0 comments

### History is keyed by the project path, so a reused path inherits another project's checkpoints — and Restore writes them over your files

Found by the full-codebase review before 0.1.9. Same area as #77, different
mechanism, and the one that can overwrite a paper you are actually working on.

`historyRepo()` picks the shadow repo's directory by hashing the project's
resolved path:

```ts
const hash = createHash('sha256').update(key).digest('hex').slice(0, 16);
return join(cacheRoot(), 'history', hash);
```

So the history belongs to the **path**, not to the project. Four consequences,
all silent:

**Rename the folder and the timel

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/79) · 2026-07-26 · closed · 0 comments

### The legacy /viewer never learns its server stopped — and no smoke has ever loaded it

The stale-window warning from #57 was added to the React workspace at `/app`. The
legacy `/viewer` never got it — and `/viewer` is what `render_preview` opens
whenever `ui/dist/index.html` is missing:

```ts
const hasWorkspace = existsSync(join(PKG_ROOT, 'ui', 'dist', 'index.html'));
…
const workspaceUrl = hasWorkspace ? `${preview.url}/app` : preview.viewerUrl;
```

which is a fresh clone before `npm run build:ui` — the from-source setup the
README documents — or any publish where the built wor

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/68) · 2026-07-26 · closed · 0 comments

### Only the toolbar was told the window is dead — the editor keeps writing to a closed port

The dead-window signal from #57 was threaded to the toolbar and nowhere else, so
every other surface keeps writing to a closed port. Found by `/code-review ultra`.

## The one that costs the user their text

`SourcePanel` is rendered with no `status`, so after the server stops:

- the 30-second autosave keeps `PUT`ting to `/api/file`,
- the Live-mode debounce does the same on every keystroke pause,
- and both fail into a bare `catch { setSaveState('error') }`.

Measured in the browser, on the sh

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/64) · 2026-07-26 · closed · 0 comments

### The shutdown added in #57 cannot finish in time, and can rebuild what it tore down

The shutdown added in #57 does not complete inside the window it has, and can
recreate the very things it just tore down. Found by `/code-review ultra`; the
first two are measured, not reasoned.

## The budget

`StdioClientTransport.close()` (@modelcontextprotocol/sdk client/stdio.js:147-166)
disconnects like this:

```
stdin.end()  →  2s  →  SIGTERM  →  2s  →  SIGKILL
```

Everything below has to finish inside that, or the process is killed still
holding Chromium and the port.

## 1. close() wa

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/62) · 2026-07-26 · closed · 0 comments

### The Node version check added in #58 is dead code, and #58's claim that no check existed is false

Follow-up to #59, correcting it.

## #59 was wrong, and so was the commit that closed it

#59 said "the README claims a startup check that does not exist" and showed:

```console
$ grep -rn "process.version" src/
$
```

That search was the mistake. `bin/cli.mjs` — the file `package.json` maps
`magictex-mcp` to — has had the check since before any of this:

```js
const MIN_MAJOR = 20;
const MIN_MINOR = 19;
const [major, minor] = process.versions.node.split('.').map(Number);
if (major < MIN_MAJOR 

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/60) · 2026-07-26 · closed · 0 comments

### Nothing is cleaned up on exit: leaked servers keep compiling, and stale tabs look alive

A user reported `render failed` from a workspace tab while a *different*, healthy
instance was compiling their paper fine on another port. Both statements were
true. The tab was pointed at a server that no longer existed, and nothing on
screen said so.

This is an audit of what the process actually cleans up when it goes away. The
answer is nothing.

## Findings

**1. Neither cleanup function is called by anything.**

```
src/engine/browserHost.ts:136   export async function shutdownEngine()
src

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/55) · 2026-07-26 · closed · 0 comments

### \includesvg fails on both backends, and the error explains neither

A paper with `\includesvg` cannot compile on either backend, and the error
explains none of it.

Real log from a user's paper:

```
wasn't possible to launch the Inkscape export
(svg)                for `fig/Fed_CMA architecture diagram2.svg' on input line 113.

! Package svg Error: File `Fed_CMA architecture diagram2_svg-tex.pdf' is missing.

Did you run the export with Inkscape? There's no file
`./svg-inkscape/Fed_CMA architecture diagram2_svg-tex.pdf'
```

The `svg` package doesn't embed SVGs

[Read the thread](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues/46) · 2026-07-26 · closed · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/ZoeLinUTS/MagicTeX-mcp/issues).
