Skip to main content
Question

use_figma: mutations followed by throw are silently rolled back — still reproducing on design files (continuation of #55837)

  • August 31, 2026
  • 1 reply
  • 5 views

Nate Peo

This is a continuation of #55837, not a new bug. Posting separately because replies to that thread are erroring out. Jaycee Lewis confirmed the behaviour there on 9 July 2026 and escalated it to the MCP team. It still reproduces on 31 August 2026, seven weeks later, and I have one piece of new information: it is not FigJam-specific. The original report was on a FigJam board. Everything below is a Figma design file.

Environment: Figma MCP server via Claude, Pro plan, Full seat. Design file (/design/). Reproduced on both a large existing production file and a brand-new empty file created via create_new_file.

The failure

Any use_figma script that mutates the file and then reports its result by throwing has the mutation rolled back. The call returns a real node ID and no error indicating a rollback, so it reads as a successful write. The node is gone by the next call.

Minimal A/B — the only variable is how the script returns data

A — report the node ID via throw:

const page = figma.currentPage;const r = figma.createRectangle();r.x = 0; r.y = 0; r.resize(50,50);r.name = "TEST_RECT_THROW";page.appendChild(r);throw new Error(JSON.stringify({id: r.id}));

Returns Error: {"id":"3:2"} — a valid node ID, no rollback signalled.
Debug UUID a38f6e4d-0e1d-4dbb-8172-7ef1da5f52dc

Next call: await figma.getNodeByIdAsync("3:2"){"exists": false}, and figma.currentPage.children is [].

B — identical script, return instead of throw:

const page = figma.currentPage;const r = figma.createRectangle();r.x = 200; r.y = 200; r.resize(50,50);r.name = "TEST_RECT_RETURN";page.appendChild(r);return { createdNodeIds: [r.id] };

Returns {"createdNodeIds":["3:3"]}. The node persists. Confirmed independently through the separate get_metadata read tool:

<canvas id="0:1" name="Page 1" width="0" height="0">  <rounded-rectangle id="3:3" name="TEST_RECT_RETURN" x="200" y="200" width="50" height="50" /></canvas>

Re-verified again the same day on a fresh node: created via return, persisted, still present on a subsequent call.

What was ruled out before finding this

Roughly 13 write/verify pairs across: two different files including a brand-new empty one, desktop app closed, desktop app open with the file focused, a fresh desktop install, a full machine restart, and an MCP server reconnect mid-session. Identical failure in every state. whoami returned correct and unchanged account, team and seat throughout, and reads of pre-existing content worked the entire time.

That consistency is what made it look like a backend fault. It was not environmental at all — every one of those attempts used throw to report the node ID, so the invariant was the script, not the machine.

Additional debug UUIDs from that sequence:

a64342bf-b78e-45f3-8f05-0d30d9edb4517f10565b-26ca-4f97-9862-f286b714acf531c17921-2f1a-4225-bbc7-8bd23f25aaea55d073cc-7860-4531-ba3a-c11f925a1e8f41597a68-9d75-4f55-8fbd-b2c771461bd02d262dea-ae6f-4665-8740-55cf40bc7a36b980d2b6-bafb-408e-ab18-28df9216bd1676edc91f-3e8a-4d3f-bacd-5a2d01ce0782ed60d0b7-c349-48f2-bbfc-1a59e5073b68cb9ed133-eb65-4b9b-aeb8-a5832bab8806eba22527-9a4b-4f31-acab-264194c34a09cb9ce79a-7a4f-4b4e-9f91-6ebc252c49d1de6e82ea-a771-4e89-bfee-8c6f727d691f   (write, new empty file)48b76be3-04dd-4888-b3f8-14628226ec8d   (verify, same file — node not found)

Why this costs people hours

The figma-use skill shipped with the MCP server contains two passages that are individually true and jointly a trap.

Section 3, "return Is Your Output Channel":

"Error info: Thrown errors are automatically captured and returned — just let them propagate or throw explicitly."

Section 7, "Error Recovery":

"use_figma is atomic — failed scripts do not execute. If a script errors, no changes are made to the file."

The first reads as an invitation to use throw as an output channel. The second means doing so discards your work. Nothing in the returned error says a rollback happened, so the natural next step is to suspect permissions, file state, the desktop app, or the backend — which is exactly the several hours this cost me, and appears to be what happened in #55837 too.

Requests, in order of how cheap they are

  1. Reconcile those two passages in the skill docs. Even with no API change, this alone would prevent most occurrences.
  2. Signal the rollback. If a script mutated the file and then threw, say so in the returned error. Silent discard is the whole problem.
  3. Consider whether a throw after successful mutations should roll back at all, given throw is currently the only way to get data out of a script that also wants to report a failure.

Workaround for anyone who lands here: use return, never throw, in any script that writes. It works reliably.

On the other two symptoms in #55837

I could not reproduce either on a design file. A cross-page appendChild onto a non-active page persisted and was confirmed by get_metadata, and reading a non-active page's children returned the correct count without setCurrentPageAsync. Caveat: the page I read had been created in the same session, so that is not a clean test of the incremental page-load path Jaycee asked about. Those two may well be genuinely FigJam-specific.

1 reply

Jaycee Lewis
Figmate

Hey ​@Nate Peo 🤩 To help keep things consolidated, I relied to you in this thread 

Thanks! – Jaycee