nsqio/nsq · error · http_api.Err

MISSING_ARG_TOPIC

MISSING_ARG_TOPIC

Error message

MISSING_ARG_TOPIC

What it means

internal/http_api.GetTopicChannelArgs parses the 'topic' and 'channel' query parameters for every channel-oriented nsqd/nsqlookupd HTTP endpoint (create channel, delete channel, pause, unpause, empty). rp.Get("topic") returns an error when the key is absent, which is reported as MISSING_ARG_TOPIC and the handler responds 400 Bad Request with that string.

Source

Thrown at internal/http_api/topic_channel_args.go:16

package http_api

import (
	"errors"

	"github.com/nsqio/nsq/internal/protocol"
)

type getter interface {
	Get(key string) (string, error)
}

func GetTopicChannelArgs(rp getter) (string, string, error) {
	topicName, err := rp.Get("topic")
	if err != nil {
		return "", "", errors.New("MISSING_ARG_TOPIC")
	}

	if !protocol.IsValidTopicName(topicName) {
		return "", "", errors.New("INVALID_ARG_TOPIC")
	}

	channelName, err := rp.Get("channel")
	if err != nil {
		return "", "", errors.New("MISSING_ARG_CHANNEL")
	}

	if !protocol.IsValidChannelName(channelName) {
		return "", "", errors.New("INVALID_ARG_CHANNEL")
	}

	return topicName, channelName, nil
}

View on GitHub (pinned to 85cf10c09c)

Solutions

  1. Add the topic query parameter: ?topic=<name>&channel=<name>.
  2. Check spelling and case - the lookup is exactly 'topic' (url.Values.Get is case-sensitive).
  3. URL-encode the value if it contains special characters such as # (ephemeral topics).

Example fix

# before
curl -X POST 'http://127.0.0.1:4151/channel/create?channel=ch'
# after
curl -X POST 'http://127.0.0.1:4151/channel/create?topic=orders&channel=ch'
Defensive patterns

Strategy: validation

Validate before calling

q := url.Values{}
if topic == "" {
	return errors.New("topic query parameter is required")
}
q.Set("topic", topic)
q.Set("channel", channel)
req, _ := http.NewRequest("POST", nsqdURL+"/channel/create", strings.NewReader(q.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

Try / catch

resp, err := http.DefaultClient.Do(req)
if err != nil { return err }
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode == 400 && strings.Contains(string(body), "MISSING_ARG_TOPIC") {
	// caller omitted the parameter: fix request construction, do not retry blindly
	return fmt.Errorf("bad request built: %s", body)
}

Prevention

When it happens

Trigger: Calling any HTTP API that uses GetTopicChannelArgs without a topic parameter, e.g. curl 'http://127.0.0.1:4151/channel/create?channel=ch' or 'http://127.0.0.1:4151/channel/pause?channel=ch'. A value of topic= (present but empty) does NOT trigger this - it fails the later name check instead.

Common situations: Hand-built curl requests with a typo in the parameter name (topics=, Topic=); client code that builds query strings with fmt.Sprintf and forgets the topic; proxies or load balancers that strip unknown query parameters.

Related errors


AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16). Data as JSON: /api/errors/0a120aa7ff28f92d. Report an issue: GitHub.