nsqio/nsq · error

string(data)

Error message

string(data)

What it means

bench_reader panics with string(data) when the frame unpacked from a response has type FrameTypeError — nsqd sent an error frame mid-stream instead of a message. The panic message is the server's error text verbatim (e.g. 'E_INVALID', 'E_BAD_TOPIC', 'E_BAD_BODY', 'E_FAILED_ID'). At this point the subscription loop is running, so the error concerns the subscribed topic/channel or message processing state.

Source

Thrown at bench/bench_reader/bench_reader.go:130

	var msgCount int64
	go func() {
		time.Sleep(td)
		_ = conn.Close()
	}()
	for {
		resp, err := nsq.ReadResponse(rw)
		if err != nil {
			if errors.Is(err, net.ErrClosed) {
				break
			}
			panic(err.Error())
		}
		frameType, data, err := nsq.UnpackResponse(resp)
		if err != nil {
			panic(err.Error())
		}
		if frameType == nsq.FrameTypeError {
			panic(string(data))
		} else if frameType == nsq.FrameTypeResponse {
			continue
		}
		msg, err := nsq.DecodeMessage(data)
		if err != nil {
			panic(err.Error())
		}
		_, err = nsq.Finish(msg.ID).WriteTo(rw)
		if err != nil {
			panic(err.Error())
		}
		msgCount++
		if float64(msgCount%int64(*rdy)) > float64(*rdy)*0.75 {
			err = rw.Flush()
			if err != nil {
				panic(err.Error())
			}
		}

View on GitHub (pinned to 85cf10c09c)

Solutions

  1. Match reader/writer topic names exactly and use valid topic strings (no slashes).
  2. Raise --msg-timeout on nsqd or lower bench -rdy so messages are finished before timeout (avoids E_FAILED_ID_NOT_WRITTEN).
  3. Ensure producers stay under --max-msg-size.
  4. Do not delete/recreate the topic/channel while the benchmark loop is active.

Example fix

# before
nsqd --msg-timeout=100ms  # FINs race timeout -> E_FAILED_ID
bench_reader -rdy=1000 ...

# after
nsqd --msg-timeout=60s
bench_reader -rdy=200 ...
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight the exact topic/channel exist via HTTP
resp, _ := http.Get(fmt.Sprintf("http://%s/topic/exists?topic=%s", httpAddr, topic))
// treat non-OK as fatal before connecting

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Fatalf("nsqd error frame: %v", r) // r is the server's error text
    }
}()

Prevention

When it happens

Trigger: Publishing to a topic that got deleted mid-benchmark (E_BAD_TOPIC / invalid topic); FIN sent for an ID already timed-out and requeued (E_FAILED_ID_NOT_WRITTEN); message body constraints violated by a concurrent producer (E_BAD_BODY, too large); channel deleted while bench_reader is attached.

Common situations: Running bench_writer and bench_reader against one topic while nsqdadmin deletes/recreates topics; message size exceeding --max-msg-size mid-run; long-running readers whose FINs race msg timeout (--msg-timeout) causing E_FAILED_ID; running other producers that violate topic-name rules (/topic is invalid).

Related errors


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