fluent/fluentd · error · Fluent::ConfigError
Invalid contents (not object) in plugin storage file: '#{@pa
Error message
Invalid contents (not object) in plugin storage file: '#{@path}' What it means
LocalStorage#configure parses the existing storage file as JSON and requires the top-level value to be a Hash (storage_local.rb:93-94); a JSON array, string, number, or true/false triggers this Fluent::ConfigError. Note a subtlety: because Fluent::ConfigError inherits from StandardError and this raise sits inside the begin/rescue at lines 87-98, the outer rescue => e catches it and re-raises as "Unexpected error: failed to read data..." (error 248), so the message you see at top level is often the 248 one while this is the root cause logged via log.error.
Source
Thrown at lib/fluent/plugin/storage_local.rb:94
end
@on_memory = true
@multi_workers_available = true
end
end
if !@on_memory
dir = File.dirname(@path)
FileUtils.mkdir_p(dir, mode: @dir_mode) unless Dir.exist?(dir)
if File.exist?(@path)
raise Fluent::ConfigError, "Plugin storage path '#{@path}' is not readable/writable" unless File.readable?(@path) && File.writable?(@path)
begin
data = File.open(@path, 'r:utf-8:utf-8') { |io| io.read }
if data.empty?
log.warn "detect empty plugin storage file during startup. Ignored: #{@path}"
return
end
data = JSON.parse(data, Fluent::DEFAULT_JSON_PARSE_OPTIONS)
raise Fluent::ConfigError, "Invalid contents (not object) in plugin storage file: '#{@path}'" unless data.is_a?(Hash)
rescue => e
log.error "failed to read data from plugin storage file", path: @path, error: e
raise Fluent::ConfigError, "Unexpected error: failed to read data from plugin storage file: '#{@path}'"
end
else
raise Fluent::ConfigError, "Directory is not writable for plugin storage file '#{@path}'" unless File.stat(dir).writable?
end
end
end
def multi_workers_ready?
unless @multi_workers_available
log.error "local plugin storage with multi workers should be configured to use directory 'path', or system root_dir and plugin id"
end
@multi_workers_available
end
def loadView on GitHub (pinned to dd45c6e18d)
Solutions
- Rewrite the storage file as a JSON object of key/value pairs, e.g. {"key":"value"}, preserving the keys the plugin expects
- If the saved state is disposable, stop fluentd, move/delete the offending file, and let LocalStorage recreate it (state resets to empty)
- Check the fluentd log for the preceding 'failed to read data from plugin storage file' entry with the original parse error to confirm the file content
- Validate the file offline before restart: ruby -rjson -e 'puts JSON.parse(File.read(ARGV[0])).class' storage.json should print Hash
Example fix
# before
$ cat /var/log/fluent/storage.json
["saved_keys"]
# => Invalid contents (not object) in plugin storage file
# after
$ cat /var/log/fluent/storage.json
{"last_save_time":"2024-01-01 00:00:00 UTC"} Defensive patterns
Strategy: validation
Validate before calling
require 'json'
path = '/var/log/fluent/storage.json'
if File.exist?(path) && !File.empty?(path)
data = JSON.parse(File.read(path))
raise "storage file must hold a JSON object, got #{data.class}" unless data.is_a?(Hash)
end Type guard
def valid_storage_file?(path) return true unless File.exist?(path) && !File.empty?(path) JSON.parse(File.read(path)).is_a?(Hash) rescue JSON::ParserError false end
Try / catch
begin
plugin.configure(conf)
rescue Fluent::ConfigError => e
if e.message.include?('failed to read data from plugin storage file')
# root cause logged just above; inspect/repair or remove the JSON file
exit 1
end
raise
end Prevention
- Never hand-edit storage files without validating top-level type is a JSON object afterward
- Keep automated repair out of band: back up storage.json before config tooling touches it
- Remember this message usually surfaces as the 'Unexpected error' wrapper (error 248) — read the paired log.error line for the true cause
When it happens
Trigger: A storage file containing e.g. [1,2,3], "text", 42, or null — valid JSON but not an object. Happens when a JSON array state file was written by another tool, a manual edit replaced the object with a scalar, or the wrong file was pointed at via path.
Common situations: Operators hand-editing storage.json and replacing the braces with an array; scripts that regenerate state files and emit the wrong top-level type; pointing path at an unrelated JSON document; truncation during a crash followed by partial repair that yielded non-object JSON.
Related errors
- Unexpected error: failed to read data from plugin storage fi
- Plugin @id or path for <storage> required when 'persistent'
- Plugin storage path '#{@path}' is not readable/writable
- Directory is not writable for plugin storage file '#{@path}'
- Cannot enable FIPS compliant mode. OpenSSL FIPS configuratio
AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21).
Data as JSON: /api/errors/d1b0abf44e8e3ee6.
Report an issue: GitHub.