warpdotdev/warp · error · Error
cleanupOrphans: runId is required.
Error message
cleanupOrphans: runId is required.
What it means
cleanupOrphans() is a Figma plugin script that deletes every scene node, page, and variable tagged with plugin data key dsb_run_id equal to the given runId. Because deletion matches on an exact string, the function refuses to run without a runId; an undefined/empty value would make cleanup meaningless and hides the fact that the tagging step never supplied an id.
Source
Thrown at resources/bundled/mcp_skills/figma/figma-generate-library/scripts/cleanupOrphans.js:24
* by a previous build run. This is safe cleanup: it uses plugin data tags,
* never name-prefix matching, so it cannot accidentally delete user-owned nodes.
*
* Use this when a build run fails mid-way and you need to reset to a clean
* slate before retrying. The function traverses the entire document looking
* for `dsb_run_id` plugin data matching `runId`.
*
* Variables and variable collections are handled separately (they are not
* scene nodes and cannot be discovered via node traversal).
*
* @param {string} runId - The dsb_run_id value to match (e.g. "ds-build-2024-001").
* @returns {Promise<{
* removedCount: number,
* removedIds: string[]
* }>}
*/
async function cleanupOrphans(runId) {
if (!runId) {
throw new Error('cleanupOrphans: runId is required.')
}
const removedIds = []
const originalPage = figma.currentPage
// --- Remove tagged scene nodes (pages, frames, components, etc.) ---
// Collect pages to remove (can't remove during iteration)
const pagesToRemove = []
for (const page of figma.root.children) {
if (page.getPluginData('dsb_run_id') === runId) {
pagesToRemove.push(page)
continue
}
// Traverse all nodes on this page
await figma.setCurrentPageAsync(page)
View on GitHub (pinned to e72fd7aacb)
Solutions
- Pass the exact dsb_run_id string used when the artifacts were tagged, e.g. await cleanupOrphans('ds-build-2024-001')
- Trace where runId originates (manifest, client storage, parameters) and log it before the call to confirm it is a non-empty string
- Add a caller-side check that fails fast and names the missing key, so the bad value is caught before entering the plugin
Example fix
// before
await cleanupOrphans(manifest.runId) // undefined if manifest lacks runId
// after
const runId = manifest.dsb_run_id
if (typeof runId !== 'string' || runId === '') {
throw new Error('manifest is missing dsb_run_id; cannot run cleanup')
}
await cleanupOrphans(runId) Defensive patterns
Strategy: validation
Validate before calling
const runId = manifest.dsb_run_id
if (typeof runId !== 'string' || runId.trim() === '') {
throw new Error(`manifest is missing dsb_run_id; refusing to run cleanup`)
}
await cleanupOrphans(runId) Type guard
function isNonEmptyRunId(value: unknown): value is string {
return typeof value === 'string' && value.trim().length > 0
} Try / catch
try {
const { removedCount } = await cleanupOrphans(runId)
figma.notify(`Removed ${removedCount} nodes`)
} catch (err) {
figma.notify(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { error: true })
throw err
} Prevention
- Share one constant for dsb_run_id between the tagging and cleanup steps
- Fail fast in the orchestrator and name the missing key before entering the plugin
- Log the runId immediately before any destructive cleanup call
When it happens
Trigger: Calling cleanupOrphans() with no argument, an empty string, or undefined/null — typically the orchestrator reads dsb_run_id from a manifest, environment, or figma.parameters and the key is absent, so undefined is passed through.
Common situations: A generate pipeline step that tags nodes with a run id (e.g. ds-build-2024-001) was skipped or stored the id under a different key; a new code path forgot to thread the runId parameter; the manifest uses run_id instead of dsb_run_id.
Related errors
- createVariableCollection: modeNames must have at least one e
- createSemanticTokens: mode "${modeName}" not found in modeId
- --claude-auth-secret is only valid with --harness claude.
- --codex-auth-secret is only valid with --harness codex.
AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16).
Data as JSON: /api/errors/3210213c9627f7c5.
Report an issue: GitHub.