{"record":{"id":"606d84f363a573cf","repo":"fluent/fluentd","slug":"plugin-id-or-path-for-storage-required-when-pe","errorCode":null,"errorMessage":"Plugin @id or path for <storage> required when 'persistent' is true","messagePattern":"Plugin @id or path for <storage> required when 'persistent' is true","errorType":"exception","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/storage_local.rb","lineNumber":70,"sourceCode":"            @multi_workers_available = false\n          elsif File.exist?(@path) && File.directory?(@path)\n            @path = File.join(@path, \"worker#{fluentd_worker_id}\", \"storage.json\")\n            @multi_workers_available = true\n          else # path file/directory doesn't exist\n            if @path.end_with?('.json') # file\n              @multi_workers_available = false\n            else # directory\n              @path = File.join(@path, \"worker#{fluentd_worker_id}\", \"storage.json\")\n              @multi_workers_available = true\n            end\n          end\n        elsif root_dir = owner.plugin_root_dir\n          basename = (conf.arg && !conf.arg.empty?) ? \"storage.#{conf.arg}.json\" : \"storage.json\"\n          @path = File.join(root_dir, basename)\n          @multi_workers_available = true\n        else\n          if @persistent\n            raise Fluent::ConfigError, \"Plugin @id or path for <storage> required when 'persistent' is true\"\n          else\n            if @autosave\n              log.warn \"both of Plugin @id and path for <storage> are not specified. Using on-memory store.\"\n            else\n              log.info \"both of Plugin @id and path for <storage> are not specified. Using on-memory store.\"\n            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 }","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/storage_local.rb#L52-L88","documentation":"Fluent::Plugin::LocalStorage raises this Fluent::ConfigError during configure when persistent true is set but there is nowhere to persist: no explicit path was given, the owning plugin has no @id (so owner.plugin_root_dir is nil and no root_dir-based file can be derived), and no system root_dir applies. Persistent storage needs a deterministic file location across restarts, and without @id or path none exists, so configuration is rejected instead of silently losing state.","triggerScenarios":"Config with <storage persistent true> (or @type local with persistent true) inside a plugin that has no @id and no path in the <storage> section, while <system> has no root_dir. For example <match ...> <storage> persistent true </storage> </match> with @id absent. Raised from LocalStorage#configure (storage_local.rb:69-70) during startup, so fluentd fails to boot the plugin.","commonSituations":"Enabling persistence for the saved-position of a tail-like plugin or a counting filter and forgetting that persistence anchors on plugin id; configs copied from examples that relied on a system-wide root_dir that is absent in the new deployment; running under a supervisor that strips plugin ids.","solutions":["Add a stable @id to the owning plugin, e.g. <filter app> @id my_counter </filter>, so the storage file is derived as <root_dir>/workerN/storage.json or storage.<arg>.json under the plugin's directory","Set an explicit path in the storage section: <storage> persistent true path /var/log/fluent/my_state </storage>","Set a system-wide root_dir in <system> (root_dir /var/log/fluent/state) so plugins with @id get deterministic storage paths","If persistence is not actually required, set persistent false and accept the on-memory store (fluentd logs a warning about the on-memory fallback)"],"exampleFix":"# before\n<filter app.**>\n  @type record_counter\n  <storage>\n    persistent true\n  </storage>\n</filter>\n# => Plugin @id or path for <storage> required when 'persistent' is true\n\n# after\n<filter app.**>\n  @type record_counter\n  @id app_record_counter\n  <storage>\n    persistent true\n  </storage>\n</filter>","handlingStrategy":"validation","validationCode":"# dry-run the config before deploying; this error is raised at configure time\nsystem('fluentd --dry-run -c /etc/fluent/fluent.conf') or raise 'fluentd config invalid'","typeGuard":null,"tryCatchPattern":"begin\n  agent.configure(conf)\nrescue Fluent::ConfigError => e\n  abort \"config rejected: #{e.message}\" # e.g. missing @id/path for persistent storage\nend","preventionTips":["Give every plugin that owns persistent state a stable @id from day one — ids are also the anchor for root_dir-based paths","Set a system root_dir in <system> so persistent storages always have a derivable location","Run fluentd --dry-run in CI on every config change; this and most ConfigErrors are caught before rollout","Treat persistent true without a persistence anchor as a lint error in config reviews"],"tags":["fluentd","storage","config-error","persistence","plugin-id","startup"],"backgroundTag":"config-missing-required-parameter","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}