fluent/fluentd · error · ArgumentError

BUG: cannot create connection for UDP

Error message

BUG: cannot create connection for UDP

What it means

ArgumentError from server_create_connection. Connection-style servers are only possible for CONNECTION_PROTOCOLS = [:tcp, :tls, :unix]; UDP is datagram-based and has no per-connection lifecycle, so proto: :udp is rejected even though :udp is a valid protocol for the helper's datagram APIs.

Source

Thrown at lib/fluent/plugin_helper/server.rb:76

      CONNECTION_PROTOCOLS = [:tcp, :tls, :unix]

      # server_create_connection(:title, @port) do |conn|
      #   # on connection
      #   source_addr = conn.remote_host
      #   source_port = conn.remote_port
      #   conn.data do |data|
      #     # on data
      #     conn.write resp # ...
      #     conn.close
      #   end
      # end
      def server_create_connection(title, port, proto: nil, bind: '0.0.0.0', shared: true, backlog: nil, tls_options: nil, **socket_options, &block)
        proto ||= (@transport_config && @transport_config.protocol == :tls) ? :tls : :tcp

        raise ArgumentError, "BUG: title must be a symbol" unless title && title.is_a?(Symbol)
        raise ArgumentError, "BUG: port must be an integer" unless port && port.is_a?(Integer)
        raise ArgumentError, "BUG: invalid protocol name" unless PROTOCOLS.include?(proto)
        raise ArgumentError, "BUG: cannot create connection for UDP" unless CONNECTION_PROTOCOLS.include?(proto)

        raise ArgumentError, "BUG: tls_options is available only for tls" if tls_options && proto != :tls

        raise ArgumentError, "BUG: block not specified which handles connection" unless block_given?
        raise ArgumentError, "BUG: block must have just one argument" unless block.arity == 1

        if proto == :tcp || proto == :tls
          socket_options[:linger_timeout] ||= @transport_config&.linger_timeout || 0
        end

        socket_options[:receive_buffer_size] ||= @transport_config&.receive_buffer_size

        socket_option_validate!(proto, **socket_options)
        socket_option_setter = ->(sock){ socket_option_set(sock, **socket_options) }

        case proto
        when :tcp
          server = server_create_for_tcp_connection(shared, bind, port, backlog, socket_option_setter, &block)

View on GitHub (pinned to dd45c6e18d)

Solutions

  1. Use the datagram APIs instead: server_create(:my_udp, port: 5160, proto: :udp) { |data, sock| ... } or server_create_udp_service
  2. If connection semantics (connect/close/write per peer) are genuinely required, switch the design to proto: :tcp or :tls

Example fix

# before
server_create_connection(:my_udp, 5160, proto: :udp) do |conn|
  ...
end

# after
server_create(:my_udp, port: 5160, proto: :udp) do |data, sock|
  sock.write("echo: #{data}")
end
Defensive patterns

Strategy: type-guard

Validate before calling

raise ArgumentError, 'use server_create for udp' if proto == :udp
server_create_connection(title, port, proto: proto) { |conn| ... }

Type guard

def connection_capable?(proto)
  %i[tcp tls unix].include?(proto)
end

# usage
if connection_capable?(proto)
  server_create_connection(title, port, proto: proto, &block)
else
  server_create(title, port: port, proto: proto, &datagram_block)
end

Prevention

When it happens

Trigger: server_create_connection(:my_udp, 5160, proto: :udp) { |conn| ... } - the caller asks for a connection server over UDP.

Common situations: Plugin authors reusing a TCP connection template and flipping proto to :udp; misunderstanding that in_udp-style sources are datagram services, not connection servers.

Related errors


AI-assisted analysis of fluent/fluentd@dd45c6e18d (2026-08-21). Data as JSON: /api/errors/ec2ad06f92de1e72. Report an issue: GitHub.