t8y2/dbx · error

destinationType must be 'queue' or 'exchange', got '%s'

Error message

destinationType must be 'queue' or 'exchange', got '%s'

What it means

applyBinding (used by both bind and unbind) requires destinationType (or destination_type) to be exactly 'queue' or 'exchange'. Any other value — including empty string or snake_case variants like 'que' — is rejected before touching the channel.

Source

Thrown at agents/drivers/rabbitmq/operations.go:577

func (s *server) unbind(params jsonObject) (any, error) {
	if err := s.applyBinding(params, false); err != nil {
		return nil, err
	}
	return okResult(), nil
}

func (s *server) applyBinding(params jsonObject, bind bool) error {
	source, err := requireBindingName(params, "source")
	if err != nil {
		return err
	}
	destination, err := requireBindingName(params, "destination")
	if err != nil {
		return err
	}
	destinationType := stringOrDefault(params, "destinationType", stringOrEmpty(params, "destination_type"))
	if destinationType != "queue" && destinationType != "exchange" {
		return fmt.Errorf("destinationType must be 'queue' or 'exchange', got '%s'", destinationType)
	}
	routingKey := stringOrDefault(params, "routingKey", stringOrEmpty(params, "routing_key"))
	arguments := bindingArguments(params)
	channel, err := s.channelFor(params)
	if err != nil {
		return err
	}
	if destinationType == "queue" {
		if bind {
			return channel.QueueBind(destination, routingKey, source, false, arguments)
		}
		return channel.QueueUnbind(destination, routingKey, source, arguments)
	}
	if bind {
		return channel.ExchangeBind(destination, routingKey, source, false, arguments)
	}
	return channel.ExchangeUnbind(destination, routingKey, source, false, arguments)
}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Set destinationType to exactly 'queue' or 'exchange' (lowercase)
  2. Check you are passing the right parameter name (destinationType or destination_type) and it is not being dropped by your serialization
  3. Normalize/validate the value in your calling code before dispatching

Example fix

// before
await client.bind({"source": "events", "destination": "orders", "destinationType": "Queue", "routingKey": "o.#"})
// after
await client.bind({"source": "events", "destination": "orders", "destinationType": "queue", "routingKey": "o.#"})
Defensive patterns

Strategy: validation

Validate before calling

function validateDestinationType(t) {
  if (t !== "queue" && t !== "exchange") {
    throw new Error(`destinationType must be 'queue' or 'exchange'`)
  }
  return t
}

Type guard

function isDestinationType(v) {
  return v === "queue" || v === "exchange"
}

Prevention

When it happens

Trigger: Calling bind/unbind with destinationType omitted (falls back to '' since destination_type is also missing), or set to misspelled/uppercase values like 'Queue', 'echange', 'topic'.

Common situations: Parameter name mismatches between caller and driver (destinationType vs destination_type), uppercase enum from another system, forgetting to pass the field entirely.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/3eb5fc1c8ff5d3c0. Report an issue: GitHub.