ruby/ruby · critical
Failed to create {log_file_path}: {err}
Error message
Failed to create {log_file_path}: {err} What it means
When YJIT is given a log file (--yjit-log=/path or RubyVM::YJIT.enable(log: '/path')), option processing opens it with create+write+truncate before your program runs. If the open fails — missing parent directory, permission denied, path is a directory — the Rust code panics with this message, which aborts the whole ruby process. The panic embeds the underlying OS error string, so the exact cause is visible.
Source
Thrown at yjit/src/options.rs:360
OPTIONS.log = Some(LogOutput::MemoryOnly);
Log::init();
},
arg_value => {
let log_file_path = if std::path::Path::new(arg_value).is_dir() {
format!("{arg_value}/yjit_{}.log", std::process::id())
} else {
arg_value.to_string()
};
match File::options().create(true).write(true).truncate(true).open(&log_file_path) {
Ok(file) => {
use std::os::unix::io::IntoRawFd;
eprintln!("YJIT log: {log_file_path}");
unsafe { OPTIONS.log = Some(LogOutput::File(file.into_raw_fd())) }
Log::init()
}
Err(err) => panic!("Failed to create {log_file_path}: {err}"),
}
}
},
("trace-exits", _) => unsafe {
OPTIONS.gen_stats = true;
OPTIONS.trace_exits = match opt_val {
"" => Some(TraceExits::All),
name => match Counter::get(name) {
Some(counter) => Some(TraceExits::Counter(counter)),
None => return None,
},
};
},
("trace-exits-sample-rate", sample_rate) => unsafe {
OPTIONS.gen_stats = true;
if OPTIONS.trace_exits.is_none() {
OPTIONS.trace_exits = Some(TraceExits::All);
}View on GitHub (pinned to 0e5b888e1c)
Solutions
- Create the parent directory first: mkdir -p the directory portion of the log path
- Use an absolute path to a known-writable location such as $TMPDIR for --yjit-log
- Read the errno embedded in the panic (Permission denied vs No such file or directory) and fix ownership/permissions accordingly
- Drop --yjit-log entirely if the log is optional
Example fix
# before ruby --yjit --yjit-log=logs/yjit.log app.rb # panics when logs/ is missing # after mkdir -p logs && ruby --yjit --yjit-log=logs/yjit.log app.rb
Defensive patterns
Strategy: validation
Validate before calling
# Guard before enabling the YJIT log
log_path = ENV['YJIT_LOG']
if log_path
dir = File.dirname(File.expand_path(log_path))
unless File.directory?(dir) && File.writable?(dir)
require 'fileutils'
FileUtils.mkdir_p(dir) rescue log_path = nil # fall back to no log file
end
end
RubyVM::YJIT.enable(log: log_path) Try / catch
Not rescuable from Ruby: the failure is a Rust panic during option processing, which aborts the process. Prevent it by validating the path (directory exists and is writable) before passing --yjit-log / enable(log:), and fall back to stderr logging when validation fails.
Prevention
- Always mkdir -p the log directory in wrapper scripts before starting ruby with --yjit-log
- Prefer absolute paths derived from a known base (Dir.tmpdir, app root) over bare relative paths
- Treat a YJIT log panic as a configuration failure: fail fast in the entrypoint, not mid-deploy
When it happens
Trigger: --yjit-log=/var/log/yjit.log without write permission; --yjit-log=out/yjit.log when out/ does not exist; a log path that points at a directory; a relative path resolved from a cwd that cannot host files (systemd, cron, container read-only fs).
Common situations: CI sandboxes with read-only or missing directories; wrapper scripts assuming a different working directory than the service manager uses; the application creating its log dir after Ruby startup has already processed YJIT options.
Related errors
- _isatty proc not found in ucrtbase.dll
- end of _isatty not found in ucrtbase.dll
- pioinfo mark not found in ucrtbase.dll
- unexpected ucrtbase.dll
- mem_size must be a Integer
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/5218291cfded1c92.
Report an issue: GitHub.