{"record":{"id":"d1b0abf44e8e3ee6","repo":"fluent/fluentd","slug":"invalid-contents-not-object-in-plugin-storage-fi","errorCode":null,"errorMessage":"Invalid contents (not object) in plugin storage file: '#{@path}'","messagePattern":"Invalid contents \\(not object\\) in plugin storage file: '#(.+?)'","errorType":"exception","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/storage_local.rb","lineNumber":94,"sourceCode":"            end\n            @on_memory = true\n            @multi_workers_available = true\n          end\n        end\n\n        if !@on_memory\n          dir = File.dirname(@path)\n          FileUtils.mkdir_p(dir, mode: @dir_mode) unless Dir.exist?(dir)\n          if File.exist?(@path)\n            raise Fluent::ConfigError, \"Plugin storage path '#{@path}' is not readable/writable\" unless File.readable?(@path) && File.writable?(@path)\n            begin\n              data = File.open(@path, 'r:utf-8:utf-8') { |io| io.read }\n              if data.empty?\n                log.warn \"detect empty plugin storage file during startup. Ignored: #{@path}\"\n                return\n              end\n              data = JSON.parse(data, Fluent::DEFAULT_JSON_PARSE_OPTIONS)\n              raise Fluent::ConfigError, \"Invalid contents (not object) in plugin storage file: '#{@path}'\" unless data.is_a?(Hash)\n            rescue => e\n              log.error \"failed to read data from plugin storage file\", path: @path, error: e\n              raise Fluent::ConfigError, \"Unexpected error: failed to read data from plugin storage file: '#{@path}'\"\n            end\n          else\n            raise Fluent::ConfigError, \"Directory is not writable for plugin storage file '#{@path}'\" unless File.stat(dir).writable?\n          end\n        end\n      end\n\n      def multi_workers_ready?\n        unless @multi_workers_available\n          log.error \"local plugin storage with multi workers should be configured to use directory 'path', or system root_dir and plugin id\"\n        end\n        @multi_workers_available\n      end\n\n      def load","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/storage_local.rb#L76-L112","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\n$ cat /var/log/fluent/storage.json\n[\"saved_keys\"]\n# => Invalid contents (not object) in plugin storage file\n\n# after\n$ cat /var/log/fluent/storage.json\n{\"last_save_time\":\"2024-01-01 00:00:00 UTC\"}","handlingStrategy":"validation","validationCode":"require 'json'\npath = '/var/log/fluent/storage.json'\nif File.exist?(path) && !File.empty?(path)\n  data = JSON.parse(File.read(path))\n  raise \"storage file must hold a JSON object, got #{data.class}\" unless data.is_a?(Hash)\nend","typeGuard":"def valid_storage_file?(path)\n  return true unless File.exist?(path) && !File.empty?(path)\n  JSON.parse(File.read(path)).is_a?(Hash)\nrescue JSON::ParserError\n  false\nend","tryCatchPattern":"begin\n  plugin.configure(conf)\nrescue Fluent::ConfigError => e\n  if e.message.include?('failed to read data from plugin storage file')\n    # root cause logged just above; inspect/repair or remove the JSON file\n    exit 1\n  end\n  raise\nend","preventionTips":["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"],"tags":["fluentd","storage","json","config-error","data-corruption","startup"],"backgroundTag":"invalid-json-format","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}