Figma Font Loading Requirements Before Text Operations: Complete Plugin Guide

Every font must be explicitly loaded via await figma.loadFontAsync({ family, style }) before reading or writing any text property in Figma plugins, or the script will throw a "font not loaded" runtime error.

When developing Figma plugins using the use_figma skill in the figma/mcp-server-guide repository, understanding font loading requirements before text operations is essential for successful script execution. The Figma Plugin API operates within a sandboxed JavaScript environment that requires explicit font initialization prior to any text manipulation. Failing to adhere to these mandatory loading sequences results in invisible text, clipped layouts, and complete script failures.

Why Font Loading Is Mandatory in the Figma Plugin Sandbox

The requirement to load fonts before text operations stems from four architectural constraints enforced by the Figma plugin runtime as documented in the MCP server guide.

  1. Sandboxed Runtime Isolation: The plugin executes in a separate JavaScript sandbox that maintains its own memory space and cannot access the Figma editor's native font cache. According to the repository documentation, this isolation prevents automatic font availability.

  2. Asynchronous Font Acquisition: Fonts may reside on local disks or remote servers, requiring asynchronous fetching. The figma.loadFontAsync() method returns a Promise that resolves only after the font data is fully available in the sandbox memory.

  3. Runtime Error Prevention: Attempting to set fontName, characters, fontSize, or any glyph-dependent property without prior loading immediately throws the "font not loaded" error. As noted in skills/figma-use/SKILL.md (Critical Rule #8, lines 28-30), this error halts the entire atomic script execution.

  4. Rendering Consistency: Loaded fonts ensure accurate text measurements for line height, width calculations, and layout positioning, preventing visual glitches like clipped text lines or incorrect bounding boxes.

The Four-Step Font Loading Workflow

The figma/mcp-server-guide repository establishes a strict workflow for font initialization before text operations. Following this sequence prevents runtime exceptions and ensures proper node creation.

  1. Collect Unique Font Descriptors: Gather distinct { family, style } objects for every font variant required by your script.

  2. Execute Parallel Loading: Use await Promise.all(fonts.map(f => figma.loadFontAsync(f))) to load multiple fonts simultaneously, optimizing performance when handling multiple styles.

  3. Modify Text Properties Only After Await: Create or modify TextNode and TextStyle objects only after the font loading Promise resolves.

  4. Return Node IDs: Always return the created or mutated node IDs in the response object, as required by the use_figma skill specification.

Code Implementation Patterns for Font Loading

Creating a Simple Text Node

The most basic pattern requires loading the font before instantiating the text node. This follows the example in skills/figma-use/references/text-style-patterns.md (lines 91-93) and enforces Critical Rule #8 from skills/figma-use/SKILL.md.

// Load the font first
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' })

// Create the text node and set its content
const txt = figma.createText()
txt.characters = 'Hello, world!'
txt.fontSize = 24
txt.fontName = { family: 'Inter', style: 'Regular' }

// Position the node away from (0,0) to avoid overlap
txt.x = 100
txt.y = 50

return { createdNodeIds: [txt.id] }

Bulk Loading for Multiple Styles

When working with design systems or multiple text styles, deduplicate font descriptors and load them in parallel. This pattern appears in skills/figma-generate-library/references/token-creation.md (line 699) and skills/figma-use/references/common-patterns.md.

// Define all fonts you will need
const fontSet = new Set()
fontSet.add(JSON.stringify({ family: 'Inter', style: 'Bold' }))
fontSet.add(JSON.stringify({ family: 'Inter', style: 'Medium' }))

// Load them in parallel
await Promise.all(
  [...fontSet].map(f => figma.loadFontAsync(JSON.parse(f)))
)

// Now safely create several styled text nodes
const headings = [
  { text: 'Title',    size: 32, font: { family: 'Inter', style: 'Bold' } },
  { text: 'Subtitle', size: 24, font: { family: 'Inter', style: 'Medium' } },
]

return { createdNodeIds: headings.map(item => {
  const node = figma.createText()
  node.fontName = item.font
  node.fontSize = item.size
  node.characters = item.text
  node.x = 100
  node.y = 50 + 60 * headings.indexOf(item)
  return node.id
})}

Updating Existing Text Styles

When modifying existing TextStyle objects, you must load the font even if it was previously used elsewhere. The skills/figma-use/references/working-with-design-systems/wwds-text-styles.md (lines 79-80) explicitly requires this for any fontName modification.

// Assume you already have a TextStyle object `style`
await figma.loadFontAsync(style.fontName) // must load before modification

style.fontSize = 18
style.lineHeight = { unit: 'PIXELS', value: 24 }

// Return the updated style ID
return { mutatedNodeIds: [style.id] }

Common Pitfalls and Solutions

Pitfall Symptom Fix
Omitted await on loadFontAsync Script proceeds, then throws "font not loaded" Always await the Promise; see SKILL rule #17 in skills/figma-use/SKILL.md
Incorrect Style String (e.g., "SemiBold" vs "Semi Bold") loadFontAsync rejects with error Probe with try/catch or use figma.listAvailableFontsAsync() to discover exact style names as noted in wwds-text-styles.md (line 80)
Loading Fonts in Tight Loops Unnecessary promises, slower execution Deduplicate first using a Set of JSON-stringified descriptors before mapping to load calls
Setting fontName Before Loading Immediate runtime error on property assignment Load before any property assignment; the rule is enforced by the plugin sandbox per plugin-api-standalone.d.ts (line 1585)
Forgetting to Return IDs Subsequent steps cannot reference created nodes Follow SKILL checklist item "MUST return ALL created/mutated node IDs"

Key Repository Files for Font Management

The figma/mcp-server-guide repository contains authoritative documentation for font handling across these specific files:

Summary

  • Font loading is mandatory: Every script must call await figma.loadFontAsync({ family, style }) before accessing any text properties.
  • Load before create: Always initialize fonts prior to calling figma.createText() or modifying fontName on existing nodes.
  • Parallelize for performance: Use Promise.all() with deduplicated font sets when handling multiple styles.
  • Return node IDs: Always return created or mutated node IDs to satisfy the use_figma skill contract.
  • Reference authoritative sources: Follow the specific file paths and line references in skills/figma-use/SKILL.md and related documentation.

Frequently Asked Questions

What happens if I skip font loading before setting text properties?

The Figma plugin sandbox immediately throws a "font not loaded" runtime error that halts the entire script execution. According to the source code in skills/figma-use/SKILL.md, this is Critical Rule #8 because the sandboxed runtime cannot access the editor's font cache without explicit asynchronous loading.

Can I load multiple fonts simultaneously in Figma plugins?

Yes. The figma.loadFontAsync() method returns a Promise, allowing you to use Promise.all() to load multiple font families and styles in parallel. The repository recommends deduplicating your font descriptors first (using a Set of JSON-stringified objects) to avoid redundant loading operations, as shown in skills/figma-generate-library/references/token-creation.md.

How do I find the correct style string for a font family?

Use figma.listAvailableFontsAsync() to retrieve the exact style names available for each font family. As documented in skills/figma-use/references/working-with-design-systems/wwds-text-styles.md (line 80), style names must match exactly (e.g., "Semi Bold" versus "SemiBold"), and this API call reveals the correct formatting for the style parameter in loadFontAsync().

Do I need to reload fonts for every plugin execution?

Yes. Because the plugin runs in a sandboxed environment that does not persist state between executions, you must call figma.loadFontAsync() every time your script runs, even for fonts that were loaded in previous executions. The font cache is isolated per script invocation according to the architectural constraints described in the repository documentation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →