{"record":{"id":"409282d51d688d02","repo":"fluent/fluentd","slug":"valid-options-are-list-join-but-got-val","errorCode":null,"errorMessage":"valid options are #{list.join(',')} but got #{val}","messagePattern":"valid options are #(.+?) but got #(.+?)","errorType":"exception","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/config/types.rb","lineNumber":128,"sourceCode":"\n    def self.symbol_value(val, opts = {}, name = nil)\n      return nil if val.nil? || val.empty?\n\n      val.delete_prefix(\":\").to_sym\n    end\n\n    SYMBOL_TYPE = Proc.new { |val, opts = {}, name = nil|\n      Config.symbol_value(val, opts, name)\n    }\n\n    def self.enum_value(val, opts = {}, name = nil)\n      return nil if val.nil?\n\n      s = val.to_sym\n      list = opts[:list]\n      raise \"Plugin BUG: config type 'enum' requires :list of symbols\" unless list.is_a?(Array) && list.all?(Symbol)\n      unless list.include?(s)\n        raise ConfigError, \"valid options are #{list.join(',')} but got #{val}\"\n      end\n      s\n    end\n\n    ENUM_TYPE = Proc.new { |val, opts = {}, name = nil|\n      Config.enum_value(val, opts, name)\n    }\n\n    INTEGER_TYPE = Proc.new { |val, opts = {}, name = nil|\n      if val.nil?\n        nil\n      elsif opts[:strict]\n        begin\n          Integer(val)\n        rescue ArgumentError, TypeError => e\n          raise ConfigError, \"#{name}: #{e.message}\"\n        end\n      else","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/config/types.rb#L110-L146","documentation":"For enum parameters (config_param :x, :enum, list: [:a, :b]), enum_value converts the value to a Symbol and checks membership in the plugin-provided :list; a miss raises ConfigError with the exact allowed set in the message. The check runs only after verifying the plugin itself supplied a Symbol array, otherwise the author-facing 'Plugin BUG' error fires first. Comparison is exact and case-sensitive after to_sym, so 'JSON' will not match :json.","triggerScenarios":"config_param :format, :enum, list: [:text, :ltsv] with 'format json' (json not in list), a typo like 'jsonn', wrong casing, or an ENV-expanded value that yields a string outside the declared list.","commonSituations":"Copy-pasting a value valid for a different plugin (e.g. 'json' where the plugin only accepts :msgpack/:text); typos in long option names; case-mismatched values; upgrading a plugin whose enum list dropped an old value.","solutions":["Use one of the values printed in the error message (they are the plugin's declared list)","Fix typos and casing — the value must match a listed symbol exactly","Check the plugin's docs/config_param declaration for the current allowed set; plugin versions sometimes narrow the list","If you own the plugin, add the value to the :list or switch the param to :string when an open-ended value is legitimate"],"exampleFix":"# before\n# config_param :format, :enum, list: [:out_file, :json, :ltsv]\n<match demo.**>\n  @type file\n  <format>\n    @type ltsvv\n  </format>\n</match>\n\n# after\n<match demo.**>\n  @type file\n  <format>\n    @type ltsv\n  </format>\n</match>","handlingStrategy":"validation","validationCode":"allowed = %i[text json ltsv] # from the plugin's :list\nunless allowed.include?(raw_value.to_sym)\n  raise ArgumentError, \"#{raw_value.inspect} not in #{allowed.join(',')}\"\nend","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy allowed values from the plugin's config_param :list, not from memory","Use a config linter/dry-run so enum typos fail in CI","Pin plugin versions so enum lists do not change under you"],"tags":["fluentd","config","enum","validation"],"backgroundTag":"enum-validation-failed","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}