AlexxIT/go2rtc · error

api.StreamNotFound

Error message

api.StreamNotFound

What it means

The MP4 WebSocket MSE handler (handlerWSMSE) resolves the target stream from the request query via streams.GetOrPatch and returns api.StreamNotFound when no stream matches. Without a stream there is no producer to negotiate MSE codecs against.

Solutions

  1. Fix the src query parameter to match an existing configured stream
  2. Add the stream to go2rtc.yaml or via the streams API before opening the WS MSE connection
  3. Verify config reload picked up newly added streams
  4. Check client code for name typos/case mismatches

Example fix

// before
ws://host:1984/api/ws?src=front_door
// after (stream defined as "frontdoor" in config)
ws://host:1984/api/ws?src=frontdoor
Defensive patterns

Strategy: validation

Validate before calling

// JS: check stream availability before MSE playback
const r = await fetch(`/api/streams?src=${encodeURIComponent(name)}`)
if (!r.ok) throw new Error(`stream ${name} does not exist`)
const ws = new WebSocket(`ws://host:1984/api/ws?src=${encodeURIComponent(name)}`)

Try / catch

// JS
try {
  ws.onmessage = handleMSE
} catch (e) {
  console.error('WS MSE failed:', e) // StreamNotFound => wrong src
}

Prevention

When it happens

Trigger: Connecting to the WS MSE endpoint (/api/ws?src=...) with a src value that has no matching stream; requesting MSE playback before the stream is defined.

Common situations: Video player frontend initialized with a stale stream name after a config change, typos in src, or a race where the player starts before the stream was added via API.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/02166e2fc5a5bd77. Report an issue: GitHub.

Appendix: source

Thrown at internal/mp4/ws.go:16

package mp4

import (
	"errors"

	"github.com/AlexxIT/go2rtc/internal/api"
	"github.com/AlexxIT/go2rtc/internal/api/ws"
	"github.com/AlexxIT/go2rtc/internal/streams"
	"github.com/AlexxIT/go2rtc/pkg/core"
	"github.com/AlexxIT/go2rtc/pkg/mp4"
)

func handlerWSMSE(tr *ws.Transport, msg *ws.Message) error {
	stream, _ := streams.GetOrPatch(tr.Request.URL.Query())
	if stream == nil {
		return errors.New(api.StreamNotFound)
	}

	var medias []*core.Media
	if codecs := msg.String(); codecs != "" {
		log.Trace().Str("codecs", codecs).Msgf("[mp4] new WS/MSE consumer")
		medias = mp4.ParseCodecs(codecs, true)
	}

	cons := mp4.NewConsumer(medias)
	cons.FormatName = "mse/fmp4"
	cons.WithRequest(tr.Request)

	if err := stream.AddConsumer(cons); err != nil {
		log.Debug().Err(err).Msg("[mp4] add consumer")
		return err
	}

	tr.Write(&ws.Message{Type: "mse", Value: mp4.ContentType(cons.Codecs())})

View on GitHub (pinned to c245815e75)