{"record":{"id":"f06754e28f45712a","repo":"fluent/fluentd","slug":"e-service-must-have-host-and-port","errorCode":null,"errorMessage":"#{e}. Service must have `host` and `port`","messagePattern":"#(.+?)\\. Service must have `host` and `port`","errorType":"exception","errorClass":"Fluent::ConfigError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin/sd_file.rb","lineNumber":138,"sourceCode":"          rescue => e\n            raise Fluent::ConfigError, \"sd_file: path=#{@path} couldn't open #{e}\"\n          end\n\n        parser.call(config_data).map do |s|\n          Service.new(\n            :file,\n            s.fetch('host'),\n            s.fetch('port'),\n            s['name'],\n            s.fetch('weight', DEFAULT_WEIGHT),\n            s['standby'],\n            s['username'],\n            s['password'],\n            s['shared_key'],\n          )\n        end\n      rescue KeyError => e\n        raise Fluent::ConfigError, \"#{e}. Service must have `host` and `port`\"\n      end\n\n      class StatWatcher < Coolio::StatWatcher\n        def initialize(path, log, &callback)\n          @path = path\n          @log = log\n          @callback = callback\n          super(@path)\n        end\n\n        def on_change(prev_stat, cur_stat)\n          @callback.call(prev_stat, cur_stat)\n        rescue => e\n          @log.error(e)\n        end\n      end\n    end\n  end","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin/sd_file.rb#L120-L156","documentation":"SdFileServiceDiscovery#fetch_server_info (lib/fluent/plugin/sd_file.rb:138) maps each YAML/JSON service entry to a Service object using Hash#fetch for 'host' and 'port' — which raise KeyError when absent — and re-wraps that as Fluent::ConfigError. Entries may omit every other field (name, weight, standby, username...) but host and port are mandatory. The error names the missing key in its message.","triggerScenarios":"A services.yaml entry like '- name: node1' (no host/port); port specified as a string key 'port:' with empty value yielding nil is accepted, but truly absent keys raise; JSON entries where host is nested one level deeper than expected; entries using 'address' instead of 'host'.","commonSituations":"Hand-editing service discovery YAML and forgetting the port; generating the file from a CMDB export with different field names; truncated YAML from a failed template render; mixing indentation so entries land under a comments/metadata key.","solutions":["Add host and port to every entry: - host: 192.0.2.1\\\\n  port: 24224.","Validate the file shape before restart (yaml parse + each entry has_key host/port).","Regenerate the file from source data with the correct field mapping.","Use fluentd --dry-run to fail fast at deploy time instead of at runtime reload."],"exampleFix":"# before\n# /etc/fluent/services.yaml\n- name: node1\n- name: node2\n  host: 192.0.2.2\n  port: 24224\n# after\n- name: node1\n  host: 192.0.2.1\n  port: 24224\n- name: node2\n  host: 192.0.2.2\n  port: 24224","handlingStrategy":"validation","validationCode":"require 'yaml'\nYAML.load_file('/etc/fluent/services.yaml').each do |s|\n  abort \"entry missing host/port: #{s}\" unless s['host'] && s.key?('port')\nend","typeGuard":"def complete_service_entry?(s)\n  s.is_a?(Hash) && s.key?('host') && s.key?('port')\nend","tryCatchPattern":null,"preventionTips":["Template services.yaml from a single source that always emits host and port.","Add a CI schema check for the discovery file.","Dry-run fluentd after regenerating discovery files."],"tags":["fluentd","service-discovery","config-error","missing-field"],"backgroundTag":"missing-required-config-field","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}