denoland/deno · error · std::io::Error
{} is not supported for an embedded deno compile file
Error message
{} is not supported for an embedded deno compile file What it means
The embedded filesystem of a `deno compile` binary is read-only and backed by a snapshot, so mutating operations cannot work. Affected ops return io::ErrorKind::Unsupported with '<op> is not supported for an embedded deno compile file' — the op names include 'writing files', 'setting file length', 'setting file times', 'locking files', 'unlocking files', 'cloning files', and timestamp reads ('accessed/created/changed/modified time' are not stored).
Source
Thrown at cli/rt/file_system.rs:738
fn is_socket(&self) -> std::io::Result<bool> {
Ok(false)
}
fn file_attributes(&self) -> std::io::Result<u32> {
Ok(0)
}
}
/// `statfs` result for a path within the embedded read-only file system.
///
/// There is no real backing device, so this reports an empty read-only file
/// system (no free space) rather than failing or leaking host disk stats.
fn vfs_statfs() -> FsStatFs {
FsStatFs::default()
}
fn not_supported(name: &str) -> std::io::Error {
std::io::Error::new(
ErrorKind::Unsupported,
format!(
"{} is not supported for an embedded deno compile file",
name
),
)
}
impl sys_traits::FsDirEntry for FileBackedVfsDirEntry {
type Metadata = BoxedFsMetadataValue;
fn file_name(&self) -> Cow<'_, std::ffi::OsStr> {
Cow::Borrowed(self.metadata.name.as_ref())
}
fn file_type(&self) -> std::io::Result<sys_traits::FileType> {
Ok(self.metadata.file_type)
}View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Write to a real filesystem location instead: use the OS temp dir (Deno.env.get('TMPDIR') || '/tmp') or a user data dir, not paths inside the compiled VFS
- Branch behavior when running compiled: detect via a build-time constant (e.g. Deno build substitution or an env var you set in the compile recipe) and pick writable locations
- Read embedded assets from the VFS but materialize writable copies (Deno.readFile -> write to temp) before APIs that need write/lock access
- Replace timestamp/lock dependencies (utime, flock) with no-ops or alternatives when operating on embedded files
Example fix
// before (fails when compiled)
const dbPath = new URL('./app.db', import.meta.url).pathname;
const db = await Deno.open(dbPath, { write: true, create: true });
// after
const dbPath = await Deno.makeTempFile({ prefix: 'app-', suffix: '.db' });
await Deno.copyFile(new URL('./seed.db', import.meta.url), dbPath);
const db = await Deno.open(dbPath, { write: true }); Defensive patterns
Strategy: fallback
Validate before calling
// Route writes away from the embedded VFS before any mutation
const IS_COMPILED = !!Deno.env.get("DENO_COMPILE") /* or your build-time flag */;
export function writablePath(rel: string): string {
if (!IS_COMPILED) return rel;
const tmp = Deno.env.get("TMPDIR") ?? "/tmp";
return `${tmp}/${crypto.randomUUID().slice(0, 8)}-${rel}`;
} Type guard
async function isWritableDir(dir: string): Promise<boolean> {
try {
const probe = await Deno.makeTempFile({ dir });
await Deno.remove(probe);
return true;
} catch { return false; }
} Try / catch
try {
await Deno.writeTextFile(configPath, data);
} catch (e) {
if (e instanceof Error && /not supported for an embedded deno compile file/i.test(e.message)) {
// VFS is read-only: redirect to a real writable location and retry once
configPath = await Deno.makeTempFile({ suffix: ".json" });
await Deno.writeTextFile(configPath, data);
} else throw e;
} Prevention
- Never write next to import.meta assets; use temp/user-data directories
- Skip flock/utime/truncate calls on embedded files in compiled builds
- Audit dependencies for lock-file and timestamp behavior before shipping compiled binaries
When it happens
Trigger: A compiled app calling Deno.open with write:true / Deno.writeFile / truncate / utime / flock on a path inside the VFS (e.g. relative paths resolving under /deno-dir/...); Node-compat libraries trying to create lock files, temp files, or update timestamps next to the executable; SQLite or bundlers attempting to write caches into their own directory.
Common situations: Apps that worked under `deno run` but break under `deno compile` because they write next to their sources; tools writing config/cache beside the binary; flock-based mutexes in ported Node libraries; utime calls in deployment scripts.
Related errors
- Not a directory
- path not found (outside root): {}
- path not found (symlink not dir): {}
- Unexpected 'name' field in options, bench name is already pr
- Unexpected second argument to Deno.bench()
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/c1d7396ce18456ed.
Report an issue: GitHub.