coleam00/Archon · error

Failed to move extracted web UI from ${tmpDir} to ${targetDi

Error message

Failed to move extracted web UI from ${tmpDir} to ${targetDir}: ${toError(err).message}

What it means

downloadWebDist stages the extracted web UI in a temp dir and then atomically renames it into the target directory; if renameSync throws, cleanupAndThrow removes the temp dir and raises this error wrapping the OS message. renameSync fails across filesystems (EXDEV) or when the destination can't be created/replaced. The atomic move guarantees the server never sees a half-installed web UI.

Source

Thrown at packages/cli/src/commands/serve.ts:272

    }
  } finally {
    rmSync(tarballPath, { force: true });
  }

  // Verify extraction produced expected layout
  if (!existsSync(`${tmpDir}/index.html`)) {
    cleanupAndThrow(
      tmpDir,
      'Extraction produced unexpected layout — index.html not found in extracted dir'
    );
  }

  // Atomic move into place
  mkdirSync(dirname(targetDir), { recursive: true });
  try {
    renameSync(tmpDir, targetDir);
  } catch (err) {
    cleanupAndThrow(
      tmpDir,
      `Failed to move extracted web UI from ${tmpDir} to ${targetDir}: ${toError(err).message}`
    );
  }
  // Closes the last phase: staged-archive removal, layout check, and the rename
  // of a freshly written tree — all after-tar filesystem work.
  log.info(
    { targetDir, durationMs: Math.round(performance.now() - extractionEndedAt) },
    'web_dist.installed'
  );
  console.log(`Extracted to ${targetDir}`);
}

function cleanupAndThrow(tmpDir: string, message: string): never {
  rmSync(tmpDir, { recursive: true, force: true });
  throw new Error(message);
}

View on GitHub (pinned to 0773b97458)

Solutions

  1. Read the wrapped OS message: EXDEV means set TMPDIR to a directory on the same filesystem as the installation, or copy-then-rename instead of rename.
  2. Remove/repair a leftover target directory from a prior failed install (stop the server first), then re-run serve.
  3. Fix permissions on the installation parent directory so mkdir/rename can succeed.
  4. On Windows, stop other processes locking the target path before retrying.

Example fix

// before
renameSync(tmpDir, targetDir); // throws EXDEV when tmp and target are different filesystems
// after
try {
  renameSync(tmpDir, targetDir);
} catch (err) {
  if ((err as NodeJS.ErrnoException).code === 'EXDEV') {
    cpSync(tmpDir, targetDir, { recursive: true });
    rmSync(tmpDir, { recursive: true, force: true });
  } else throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { statSync } from 'node:fs';
const tmpDev = statSync(tmpDir).dev;
const targetDev = statSync(dirname(targetDir)).dev;
if (tmpDev !== targetDev) {
  throw new Error(`rename would fail (EXDEV): TMPDIR (${tmpDir}) and target (${targetDir}) are on different filesystems; set TMPDIR to ${dirname(targetDir)}`);
}
if (existsSync(targetDir)) {
  throw new Error(`Target ${targetDir} already exists; stop the server and remove it before upgrading`);
}

Try / catch

try {
  await serveCommand();
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Failed to move extracted web UI')) {
    if (err.message.includes('EXDEV') || err.message.includes('cross-device')) {
      // set TMPDIR to a directory on the same filesystem as the install, retry
    } else if (err.message.includes('EBUSY') || err.message.includes('EPERM')) {
      // stop processes locking the target (esp. Windows), retry
    }
  } else throw err;
}

Prevention

When it happens

Trigger: serveCommand -> downloadWebDist calls renameSync(tmpDir, targetDir) and it throws: temp dir and target on different filesystems (EXDEV), target path's parent not creatable (permissions), target existing as a non-empty dir/file that can't be replaced, or the target locked by a running process (EBUSY, Windows).

Common situations: TMPDIR on tmpfs while the install lives on the root filesystem (classic cross-device rename); read-only install prefix; leftover corrupt target dir from a previous failed install; another archon process holding the target open on Windows.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/1b26091149d5fbcb. Report an issue: GitHub.