fluent/fluentd · critical · Fluent::InvalidRootDirectory

failed to create root directory:#{root_dir}, #{e.inspect}

Error message

failed to create root directory:#{root_dir}, #{e.inspect}

What it means

Fluentd raises Fluent::InvalidRootDirectory during startup when the <system> root_dir path does not exist and FileUtils.mkdir_p fails to create it (lib/fluent/supervisor.rb:719). The nested e.inspect in the message carries the underlying filesystem error, such as Errno::EACCES or Errno::ENOSPC. This happens before any plugin starts, so the whole fluentd process aborts during configuration/boot.

Source

Thrown at lib/fluent/supervisor.rb:719

      if @system_config.workers < 1
        raise Fluent::ConfigError, "invalid number of workers (must be > 0):#{@system_config.workers}"
      end

      if Fluent.windows? && @system_config.with_source_only
        raise Fluent::ConfigError, "with-source-only is not supported on Windows"
      end

      root_dir = @system_config.root_dir
      if root_dir
        if File.exist?(root_dir)
          unless Dir.exist?(root_dir)
            raise Fluent::InvalidRootDirectory, "non directory entry exists:#{root_dir}"
          end
        else
          begin
            FileUtils.mkdir_p(root_dir, mode: @system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION)
          rescue => e
            raise Fluent::InvalidRootDirectory, "failed to create root directory:#{root_dir}, #{e.inspect}"
          end
        end
      end

      begin
        ServerEngine::Privilege.change(@chuser, @chgroup)
        MessagePackFactory.init(enable_time_support: @system_config.enable_msgpack_time_support)
        Fluent::Engine.init(@system_config, supervisor_mode: true, start_in_parallel: ENV.key?("FLUENT_RUNNING_IN_PARALLEL_WITH_OLD"))
        Fluent::Engine.run_configure(@conf, dry_run: dry_run)
      rescue Fluent::ConfigError => e
        $log.error 'config error', file: @config_path, error: e
        $log.debug_backtrace
        exit!(1)
      rescue ScriptError => e # LoadError, NotImplementedError, SyntaxError
        if e.respond_to?(:path)
          $log.error e.message, path: e.path, error: e
        else
          $log.error e.message, error: e

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Check the underlying error in the message (e.inspect) — Errno::EACCES means permissions, Errno::ENOSPC means disk full
  2. If permission denied: chown or chmod the parent directory so the fluentd user can create it (e.g. install -d -o fluent -g fluent /var/log/fluent)
  3. If running in a container, ensure the volume mounted at root_dir is writable by the container user (fsGroup / runAsUser in Kubernetes, or chown in an entrypoint)
  4. Pre-create the directory yourself before starting fluentd so mkdir_p is never called
  5. For SELinux denials, set the correct context (restorecon) or adjust the policy for the fluentd process

Example fix

# before
<system>
  root_dir /var/log/fluent/buffer   # owned by root, fluentd runs as 'fluent'
</system>

# after (option 1: pre-create with correct ownership)
#   sudo install -d -o fluent -g fluent /var/log/fluent/buffer
# after (option 2: point root_dir somewhere writable)
<system>
  root_dir /home/fluent/spool
</system>
Defensive patterns

Strategy: validation

Validate before calling

require 'fileutils'

root_dir = '/var/log/fluent'
# pre-flight check mirroring supervisor.rb logic
if File.exist?(root_dir)
  abort "#{root_dir} exists but is not a directory" unless Dir.exist?(root_dir)
else
  begin
    FileUtils.mkdir_p(root_dir)
  rescue => e
    abort "cannot create #{root_dir}: #{e.class} #{e.message} — check permissions/disk"
  end
end
# also verify writability of the final directory
abort "#{root_dir} not writable" unless File.writable?(root_dir)

Prevention

When it happens

Trigger: Setting <system> root_dir /path/to/dir where the parent path is not writable by the fluentd user, the disk or inode quota is exhausted, a symlink in the path is broken, or the path crosses a read-only mount. Also triggered when root_dir points somewhere SELinux denies creation for the fluentd process context.

Common situations: Running fluentd as a low-privileged user while root_dir points under /var/log/fluent or a Docker volume owned by root; deploying to Kubernetes with an emptyDir/volumeMount whose ownership does not match the container UID; SELinux/AppArmor denying writes; full disk filling /tmp.

Related errors


AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21). Data as JSON: /api/errors/4fef8f103da79a67. Report an issue: GitHub.