shadcn-ui/ui · error · ApplyWorkspaceSyncError
Failed to sync linked workspace configs. ${error.message}
Error message
Failed to sync linked workspace configs. ${error.message} What it means
Wrap-around error thrown at the end of the apply workspace-sync catch block. Any exception inside the sync try — a FileBackupError (#20), fs.writeJson failing with ENOSPC/EACCES, or JSON serialization failure — triggers restoreFileBackup for every workspace in reverse order, then rethrows as ApplyWorkspaceSyncError with the original cause appended.
Source
Thrown at packages/shadcn/src/commands/apply.ts:513
...patch,
tailwind: {
...workspaceConfig.existingConfig.tailwind,
...patch.tailwind,
},
},
{ spaces: 2 }
)
}
for (const workspaceConfig of workspaceConfigs) {
deleteFileBackup(workspaceConfig.configPath)
}
} catch (error) {
for (const workspaceConfig of [...workspaceConfigs].reverse()) {
restoreFileBackup(workspaceConfig.configPath)
}
throw new ApplyWorkspaceSyncError(
`Failed to sync linked workspace configs.${error instanceof Error ? ` ${error.message}` : ""}`
)
}
}
async function getApplyWorkspaceConfigs(config: Config) {
const workspaceConfig = await getWorkspaceConfig(config)
if (!workspaceConfig) {
return []
}
const linkedConfigs = new Map<string, Config>()
for (const linkedConfig of Object.values(workspaceConfig)) {
if (linkedConfig.resolvedPaths.cwd === config.resolvedPaths.cwd) {
continue
}
View on GitHub (pinned to efac598707)
Solutions
- Read the original cause after the period in the message — it tells you which workspace and why.
- Free disk space on the volume holding the linked workspaces (ENOSPC).
- Check write permissions on every workspace's components.json, not just the root.
- Verify each linked workspace path declared in components.json still exists and is writable.
- If the rollback did not complete, manually restore each components.json from its components.json.bak.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before apply: assert every workspace config path is writable, not just root.
import fs from "fs-extra"
async function preflightWorkspaceWrite(configPaths: string[]) {
for (const p of configPaths) {
await fs.access(p, fs.constants.W_OK)
}
} Type guard
function isApplyWorkspaceSyncError(e: unknown): e is Error {
return e instanceof Error && e.name === "ApplyWorkspaceSyncError"
} Try / catch
try {
await applyToWorkspaces(config)
} catch (e) {
if (isApplyWorkspaceSyncError(e)) {
// The underlying cause is appended after the period in e.message.
// Backups were already restored in reverse; verify each config:
for (const p of workspaceConfigPaths) {
const bak = `${p}.bak`
if (await fs.pathExists(bak)) await fs.move(bak, p, { overwrite: true })
}
}
throw e
} Prevention
- Keep linked workspaces on the same writable volume as the root.
- Run apply from the monorepo root with all packages checked out writable.
- Confirm disk space and write access before running apply in CI.
When it happens
Trigger: Any exception raised inside apply.ts:482-507 during linked-workspace config sync. The appended `error.message` identifies the underlying cause: disk full (ENOSPC), permission denied writing a workspace components.json, or a FileBackupError from #20.
Common situations: Disk full mid-write, one linked workspace on a network mount that drops, components.json made read-only after the initial readJson, partial state from a previous crashed apply, monorepo with one package on a clean git checkout (read-only).
Related errors
- Could not back up ${filePath}.
- Failed to read config at ${options.cwd}.
- Missing value for --only. Use one or more of: ${APPLY_ONLY_V
- Invalid value for --only: ${value}. Use one or more of: ${AP
- Missing preset for --only. Use: shadcn apply <preset> --only
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/949c63fc3ed4e4ca.
Report an issue: GitHub.