wasmerio/wasmer · error

cannot create debug directory: {}

Error message

cannot create debug directory: {}

What it means

CraneliftCompilerConfig's base_path creates (create_dir_all) the debug output directory — optionally under a module hash subdirectory — used to dump preopt IR, object files, and asm during compilation. If directory creation fails (permissions, read-only filesystem, path conflicts), it panics. This only happens when debug output is enabled, so it never affects normal compilation.

Source

Thrown at lib/compiler-cranelift/src/config.rs:49

    /// Creates a new instance of `CraneliftCallbacks` with the specified debug directory.
    pub fn new(debug_dir: PathBuf) -> Result<Self, io::Error> {
        // Create the debug dir in case it doesn't exist
        std::fs::create_dir_all(&debug_dir)?;
        Ok(Self { debug_dir })
    }

    /// Returns the debug directory where the debug files are written.
    pub fn debug_dir(&self) -> &PathBuf {
        &self.debug_dir
    }

    fn base_path(&self, module_hash: &Option<String>) -> PathBuf {
        let mut path = self.debug_dir.clone();
        if let Some(hash) = module_hash {
            path.push(hash);
        }
        std::fs::create_dir_all(&path)
            .unwrap_or_else(|_| panic!("cannot create debug directory: {}", path.display()));
        path
    }

    /// Writes the pre-optimization intermediate representation to a debug file.
    pub fn preopt_ir(&self, kind: &CompiledKind, module_hash: &Option<String>, mem_buffer: &[u8]) {
        let mut path = self.base_path(module_hash);
        path.push(function_kind_to_filename(kind, ".preopt.clif"));
        let mut file =
            File::create(path).expect("Error while creating debug file from Cranelift IR");
        file.write_all(mem_buffer).unwrap();
    }

    /// Writes the object file memory buffer to a debug file.
    pub fn obj_memory_buffer(
        &self,
        kind: &CompiledKind,
        module_hash: &Option<String>,
        mem_buffer: &[u8],

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Point the Cranelift debug_dir at a directory the process can write (e.g. /tmp/cranelift-debug or a mounted volume).
  2. Disable debug output (remove the debug dir setting / unset the debug env var) if dumps aren't needed.
  3. Check the path: ensure no regular file occupies the target path and parent directories are creatable.
  4. Run the compiler as a user with write permission on the configured directory.

Example fix

// before
export WASMER_CRANELIFT_DEBUG_DIR=/var/lib/wasmer/debug # read-only fs
// after
export WASMER_CRANELIFT_DEBUG_DIR=/tmp/wasmer-debug && mkdir -p /tmp/wasmer-debug
Defensive patterns

Strategy: validation

Validate before calling

// Before enabling Cranelift debug dumps, ensure the dir is writable:
use std::fs;
fn debug_dir_usable(dir: &std::path::Path) -> bool {
    fs::create_dir_all(dir).is_ok() && fs::metadata(dir).map(|m| m.is_dir()).unwrap_or(false)
}

Prevention

When it happens

Trigger: Compilation with Cranelift debug features enabled where base_path is called by preopt_ir, obj_memory_buffer, or asm_memory_buffer and std::fs::create_dir_all fails: debug_dir points somewhere non-writable/nonexistent-parent, or a file exists at the path.

Common situations: Enabling Cranelift debug dumps (WASMER_CRANELIFT_DEBUG_DIR / config debug_dir) in production containers with read-only rootfs; permission mismatch between the running user and the configured debug dir; module-hash subdirectory colliding with an existing regular file.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/6eb4c6d8b3bded97. Report an issue: GitHub.