nsqio/nsq · error · http_api.Err

INVALID_ARG_TOPIC

INVALID_ARG_TOPIC

Error message

INVALID_ARG_TOPIC

What it means

After the topic parameter is present, GetTopicChannelArgs validates it with protocol.IsValidTopicName, which enforces the regex ^[.a-zA-Z0-9_-]+(#ephemeral)?$ plus a length of 1..64 characters. A value that fails (including an empty string) returns INVALID_ARG_TOPIC and the HTTP handler responds 400.

Source

Thrown at internal/http_api/topic_channel_args.go:20

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. Use only letters, digits, dot, underscore, hyphen (optionally the #ephemeral suffix) and 1-64 chars, e.g. topic=orders.created
  2. Sanitize generated topic names at the publisher: replace invalid characters with '_' or '-' before the first publish.
  3. If the name came from URL decoding, verify it is non-empty after decode.

Example fix

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

Strategy: validation

Validate before calling

var validTopicChannelNameRegex = regexp.MustCompile(`^[.a-zA-Z0-9_-]+(#ephemeral)?$`)

func isValidNSQName(name string) bool {
	return len(name) >= 1 && len(name) <= 64 && validTopicChannelNameRegex.MatchString(name)
}

if !isValidNSQName(topic) {
	return fmt.Errorf("invalid topic name %q", topic)
}

Type guard

func isValidTopicName(name string) bool {
	return len(name) >= 1 && len(name) <= 64 && validTopicChannelNameRegex.MatchString(name)
}

Try / catch

if resp.StatusCode == 400 && strings.Contains(string(body), "INVALID_ARG_TOPIC") {
	topic = sanitizeNSQName(topic) // replace [^.a-zA-Z0-9_-] with '_' , truncate to 64
	// rebuild and retry once
}

Prevention

When it happens

Trigger: Passing a topic containing spaces, slashes, unicode, or other characters outside [.a-zA-Z0-9_-], e.g. ?topic=order/events or ?topic=order queue; passing topic= (empty); passing a name longer than 64 characters. Note that topic#ephemeral IS allowed by the regex.

Common situations: Deriving topic names from user input, file paths, or free-form event types without sanitizing; splitting a topic on '/' and accidentally keeping the separator; names trimmed to nothing after URL decoding.

Related errors


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