fluent/fluentd · error · Fluent::ConfigError

Unreloadable plugin: #{Fluent::Plugin.lookup_type_from_class

Error message

Unreloadable plugin: #{Fluent::Plugin.lookup_type_from_class(plugin.class)}, plugin_id: #{plugin.plugin_id}, class_name: #{plugin.class})

What it means

On config reload (SIGHUP / reload RPC), Fluent::Engine.reload_config builds a new RootAgent and runs Fluent::StaticConfigAnalysis over the new conf; every plugin found must report reloadable_plugin? true or the reload is rejected with this ConfigError before the running agent is swapped. The old configuration keeps serving traffic (the engine restores the previous root agent on failure), so this is a reload-rejected error, not a crash. The message names the plugin type, its @id, and the class so the offender is identifiable.

Source

Thrown at lib/fluent/engine.rb:189

      end

      @root_agent_mutex.synchronize do
        stop_phase(@root_agent)
      end
    end

    # @param conf [Fluent::Config]
    # @param supervisor [Bool]
    # @return nil
    def reload_config(conf, supervisor: false)
      @root_agent_mutex.synchronize do
        # configure first to reduce down time while restarting
        new_agent = RootAgent.new(log: log, system_config: @system_config)
        ret = Fluent::StaticConfigAnalysis.call(conf, workers: system_config.workers)

        ret.all_plugins.each do |plugin|
          if plugin.respond_to?(:reloadable_plugin?) && !plugin.reloadable_plugin?
            raise Fluent::ConfigError, "Unreloadable plugin: #{Fluent::Plugin.lookup_type_from_class(plugin.class)}, plugin_id: #{plugin.plugin_id}, class_name: #{plugin.class})"
          end
        end

        # Assign @root_agent to new root_agent
        # for https://github.com/fluent/fluentd/blob/fcef949ce40472547fde295ddd2cfe297e1eddd6/lib/fluent/plugin_helper/event_emitter.rb#L50
        old_agent, @root_agent = @root_agent, new_agent
        begin
          @root_agent.configure(conf)
        rescue
          @root_agent = old_agent
          raise
        end

        unless @suppress_config_dump
          $log.info :supervisor, "using configuration file: #{conf.to_s.rstrip}"
        end

        # supervisor doesn't handle actual data. so the following code is unnecessary.

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Do a full restart (stop + start) instead of SIGHUP for configs containing non-reloadable plugins
  2. Identify the plugin from the message (type, plugin_id, class) and remove or replace it in the new config
  3. Upgrade the plugin to a version that declares itself reloadable, or ask its maintainer to support reload
  4. If you own the plugin, make it reload-safe and have it answer reloadable_plugin? with true

Example fix

# before: SIGHUP-based deploy with a non-reloadable plugin
kill -HUP $(cat /var/run/fluentd.pid)   # reload rejected

# after: restart when the config contains non-reloadable plugins
systemctl restart fluentd
Defensive patterns

Strategy: try-catch

Validate before calling

# Pre-flight: static analysis of the new config before SIGHUP
ret = Fluent::StaticConfigAnalysis.call(new_conf, workers: 4)
bad = ret.all_plugins.reject { |p| !p.respond_to?(:reloadable_plugin?) || p.reloadable_plugin? }
abort 'reload would be rejected' unless bad.empty?

Try / catch

begin
  Fluent::Engine.reload_config(new_conf)
rescue Fluent::ConfigError => e
  log.warn "config reload rejected, keeping previous config: #{e.message}"
  # old config keeps running; schedule a full restart instead
end

Prevention

When it happens

Trigger: Sending SIGHUP (or invoking the config reload RPC) with a new config that contains a plugin whose class defines reloadable_plugin? false — typically certain input plugins and many third-party plugins; adding a brand-new non-reloadable plugin in an updated config; upgrading a plugin that dropped reload support.

Common situations: Using SIGHUP in deployment pipelines assuming zero-downtime reload; third-party plugins that never declared reload support; mixing a non-reloadable input into a previously reloadable pipeline.

Related errors


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