{"record":{"id":"8ca7e60ea0baa692","repo":"fluent/fluentd","slug":"bug-tls-options-is-available-only-for-tls","errorCode":null,"errorMessage":"BUG: tls_options is available only for tls","messagePattern":"BUG: tls_options is available only for tls","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/fluent/plugin_helper/server.rb","lineNumber":78,"sourceCode":"      # server_create_connection(:title, @port) do |conn|\n      #   # on connection\n      #   source_addr = conn.remote_host\n      #   source_port = conn.remote_port\n      #   conn.data do |data|\n      #     # on data\n      #     conn.write resp # ...\n      #     conn.close\n      #   end\n      # end\n      def server_create_connection(title, port, proto: nil, bind: '0.0.0.0', shared: true, backlog: nil, tls_options: nil, **socket_options, &block)\n        proto ||= (@transport_config && @transport_config.protocol == :tls) ? :tls : :tcp\n\n        raise ArgumentError, \"BUG: title must be a symbol\" unless title && title.is_a?(Symbol)\n        raise ArgumentError, \"BUG: port must be an integer\" unless port && port.is_a?(Integer)\n        raise ArgumentError, \"BUG: invalid protocol name\" unless PROTOCOLS.include?(proto)\n        raise ArgumentError, \"BUG: cannot create connection for UDP\" unless CONNECTION_PROTOCOLS.include?(proto)\n\n        raise ArgumentError, \"BUG: tls_options is available only for tls\" if tls_options && proto != :tls\n\n        raise ArgumentError, \"BUG: block not specified which handles connection\" unless block_given?\n        raise ArgumentError, \"BUG: block must have just one argument\" unless block.arity == 1\n\n        if proto == :tcp || proto == :tls\n          socket_options[:linger_timeout] ||= @transport_config&.linger_timeout || 0\n        end\n\n        socket_options[:receive_buffer_size] ||= @transport_config&.receive_buffer_size\n\n        socket_option_validate!(proto, **socket_options)\n        socket_option_setter = ->(sock){ socket_option_set(sock, **socket_options) }\n\n        case proto\n        when :tcp\n          server = server_create_for_tcp_connection(shared, bind, port, backlog, socket_option_setter, &block)\n        when :tls\n          transport_config = if tls_options","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/fluent/fluentd/blob/dd45c6e18dc7be33b5e5a0f0767bf46307ff5626/lib/fluent/plugin_helper/server.rb#L60-L96","documentation":"ArgumentError from server_create_connection. tls_options (cert/verify settings for the connection server) only apply when proto is :tls; passing them together with :tcp or :unix - including the implicit default, which is :tcp unless the plugin's <transport tls> is configured - is contradictory and rejected.","triggerScenarios":"server_create_connection(:srv, 24224, proto: :tcp, tls_options: {insecure: true}), or tls_options passed without proto: while the transport config is tcp/plain.","commonSituations":"Copy-pasting a TLS server snippet and changing proto to :tcp but leaving tls_options; assuming the helper silently ignores irrelevant options; forgetting <transport tls> in the plugin config so the proto default stays :tcp while tls_options are given.","solutions":["Set proto: :tls (or add <transport tls> so the default resolves to :tls) and keep the tls_options","Remove tls_options when intentionally running plaintext :tcp/:unix","Review whether the options belong in <transport tls> of the config instead of the API call"],"exampleFix":"# before\nserver_create_connection(:srv, 24224, proto: :tcp,\n                         tls_options: {insecure: true}) { |conn| ... }\n\n# after\nserver_create_connection(:srv, 24224, proto: :tls,\n                         tls_options: {insecure: true}) { |conn| ... }","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'tls_options requires proto :tls' if tls_options && proto != :tls\nserver_create_connection(title, port, proto: proto, tls_options: tls_options) { |conn| ... }","typeGuard":null,"tryCatchPattern":"begin\n  server_create_connection(title, port, proto: proto, tls_options: tls_options, &block)\nrescue ArgumentError => e\n  raise ArgumentError, \"#{e.message} (proto=#{proto.inspect}, tls_options=#{tls_options.inspect})\"\nend","preventionTips":["Pass tls_options only in the same code path that sets proto: :tls","Drive TLS settings from <transport tls> in config instead of hand-built option hashes","Test the TLS and plain branches separately"],"tags":["fluentd","server","tls","argument-error","plugin-helper"],"backgroundTag":"protocol-option-mismatch","analyzedSha":"dd45c6e18dc7be33b5e5a0f0767bf46307ff5626","analyzedAt":"2026-08-21T16:22:07.332Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}