warpdotdev/warp · error · Error

createSemanticTokens: mode "${modeName}" not found in modeId

Error message

createSemanticTokens: mode "${modeName}" not found in modeIds for token "${token.name}". Available modes: ${Object.keys(modeIds).join(', ')}

What it means

createSemanticTokens.js creates one Figma variable per token and sets a value for each mode, looking the modeId up in the modeIds map produced by createVariableCollection(name, modeNames). The error fires when a token's values object has a key (mode name) with no entry in modeIds — the token file and the collection's modes are out of sync. The message lists the available modes to make the mismatch obvious.

Source

Thrown at resources/bundled/mcp_skills/figma/figma-generate-library/scripts/createSemanticTokens.js:46

 */
async function createSemanticTokens(collection, modeIds, tokenMap, runId) {
  const variables = {}

  for (const token of tokenMap) {
    // Create the variable
    const variable = figma.variables.createVariable(token.name, collection, token.type)

    // Tag for cleanup
    variable.setPluginData('dsb_key', `variable/${token.name}`)
    if (runId) {
      variable.setPluginData('dsb_run_id', runId)
    }

    // Set values for each mode
    for (const [modeName, rawValue] of Object.entries(token.values)) {
      const modeId = modeIds[modeName]
      if (!modeId) {
        throw new Error(
          `createSemanticTokens: mode "${modeName}" not found in modeIds for token "${token.name}". ` +
            `Available modes: ${Object.keys(modeIds).join(', ')}`,
        )
      }

      let value = rawValue

      // Convert hex strings to Figma RGBA for COLOR type
      if (token.type === 'COLOR' && typeof rawValue === 'string' && rawValue.startsWith('#')) {
        value = hexToFigmaColor(rawValue)
      }

      variable.setValueForMode(modeId, value)
    }

    // Set scopes (default: empty array = hidden from property pickers / primitives)
    variable.scopes = token.scopes || []

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Align the keys of token.values with the exact modeNames array passed to createVariableCollection (matching is case-sensitive)
  2. Pass the modeIds map returned by createVariableCollection straight into createSemanticTokens instead of rebuilding it
  3. Pre-validate that every key of every token.values exists in modeIds before creating any variable, so a mismatch does not leave a half-built collection behind

Example fix

// before
const { modeIds } = await createVariableCollection('Color', ['Light', 'Dark'], runId)
await createSemanticTokens([
  { name: 'bg/primary', type: 'COLOR', values: { light: '#ffffff', dark: '#000000' } },
], modeIds) // throws: mode "light" not found in modeIds

// after
const { modeIds } = await createVariableCollection('Color', ['Light', 'Dark'], runId)
await createSemanticTokens([
  { name: 'bg/primary', type: 'COLOR', values: { Light: '#ffffff', Dark: '#000000' } },
], modeIds)
Defensive patterns

Strategy: validation

Validate before calling

const modes = Object.keys(modeIds)
for (const token of tokens) {
  for (const modeName of Object.keys(token.values)) {
    if (!(modeName in modeIds)) {
      throw new Error(`token ${token.name} references unknown mode "${modeName}"; collection has: ${modes.join(', ')}`)
    }
  }
}
await createSemanticTokens(tokens, modeIds, runId)

Type guard

function modesCovered(token, modeIds) {
  return Object.keys(token.values).every((m) => m in modeIds)
}

Try / catch

try {
  await createSemanticTokens(tokens, modeIds, runId)
} catch (err) {
  if (err instanceof Error && err.message.includes('not found in modeIds')) {
    // re-align token.values keys with the collection's modeNames, then re-run
  }
  throw err
}

Prevention

When it happens

Trigger: Collection created with modeNames ['Light','Dark'] but token.values keyed 'light'/'dark' (case mismatch); a token referencing a third mode like 'HighContrast' that was never passed to createVariableCollection; a modeIds map built from a different collection than the one the variable was created in.

Common situations: Design-token JSON authored separately from the pipeline config; renaming modes in the token file without updating the collection step; token sets copied from another theme system that uses 'default' instead of 'Value'.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/bed817181f8b79fe. Report an issue: GitHub.