m1k1o/neko · error

not allowed to watch

Error message

not allowed to watch

What it means

signalRequest starts a WebRTC negotiation so the user can watch the stream. It first checks session.Profile().CanWatch; if the authenticated member lacks the 'watch' permission it refuses with this error and no peer connection is created. It is an authorization error tied to the member profile configured by the host/admin.

Source

Thrown at server/internal/websocket/handler/signal.go:15

package handler

import (
	"errors"

	"github.com/m1k1o/neko/server/pkg/types"
	"github.com/m1k1o/neko/server/pkg/types/event"
	"github.com/m1k1o/neko/server/pkg/types/message"

	"github.com/pion/webrtc/v4"
)

func (h *MessageHandlerCtx) signalRequest(session types.Session, payload *message.SignalRequest) error {
	if !session.Profile().CanWatch {
		return errors.New("not allowed to watch")
	}

	offer, peer, err := h.webrtc.CreatePeer(session)
	if err != nil {
		return err
	}

	// set webrtc as paused if session has private mode enabled
	if session.PrivateModeEnabled() {
		peer.SetPaused(true)
	}

	video := payload.Video

	// use default first video, if not provided
	if video.Selector == nil {
		videos := h.capture.Video().IDs()
		video.Selector = &types.StreamSelector{

View on GitHub (pinned to b0f01cedea)

Solutions

  1. Grant the session's member profile CanWatch=true (via admin API / members management) if the user should watch
  2. Use an account/profile type that has watch permission
  3. Update the client to not send signal requests from sessions without watch permission, and show a permission-denied UI instead
  4. If permissions changed, reconnect so the session picks up the new profile

Example fix

// before (server config)
{"name": "limited", "canWatch": false}
// after
{"name": "limited", "canWatch": true}
Defensive patterns

Strategy: validation

Validate before calling

if !session.Profile().CanWatch {
  // do not send signal/request
  return errors.New("watch permission required")
}

Type guard

func canWatch(s types.Session) bool { return s.Profile().CanWatch }

Try / catch

err := handler.SignalRequest(...)
if err != nil && strings.Contains(err.Error(), "not allowed to watch") {
  // show permission-denied UI to the user
}

Prevention

When it happens

Trigger: A user whose member profile has CanWatch=false sends a signal/request message; a host with restricted permissions tries to view the stream; permissions changed server-side while the client still assumes it can watch.

Common situations: Connecting as a host/limited-user account type that is not allowed to view streams; admin removed watch permission from the user's profile; a client (e.g. the web app) sends a watch request from a control-only session.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of m1k1o/neko@b0f01cedea (2026-09-01). Data as JSON: /api/errors/da1e00f99c58857f. Report an issue: GitHub.