{"record":{"id":"236ad55228ad3478","repo":"m1k1o/neko","slug":"errisnotallowedtohost","errorCode":"ErrIsNotAllowedToHost","errorMessage":"is not allowed to host","messagePattern":"is not allowed to host","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/websocket/handler/control.go","lineNumber":13,"sourceCode":"package handler\n\nimport (\n\t\"errors\"\n\n\t\"github.com/m1k1o/neko/server/pkg/types\"\n\t\"github.com/m1k1o/neko/server/pkg/types/event\"\n\t\"github.com/m1k1o/neko/server/pkg/types/message\"\n\t\"github.com/m1k1o/neko/server/pkg/xorg\"\n)\n\nvar (\n\tErrIsNotAllowedToHost = errors.New(\"is not allowed to host\")\n\tErrIsNotTheHost       = errors.New(\"is not the host\")\n\tErrIsAlreadyTheHost   = errors.New(\"is already the host\")\n\tErrIsAlreadyHosted    = errors.New(\"is already hosted\")\n)\n\nfunc (h *MessageHandlerCtx) controlRelease(session types.Session) error {\n\tif !session.Profile().CanHost || session.PrivateModeEnabled() {\n\t\treturn ErrIsNotAllowedToHost\n\t}\n\n\tif !session.IsHost() {\n\t\treturn ErrIsNotTheHost\n\t}\n\n\th.desktop.ResetKeys()\n\tsession.ClearHost()\n\n\treturn nil","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/m1k1o/neko/blob/b0f01cedea68893e85a3fd852c0521238c285695/server/internal/websocket/handler/control.go#L1-L31","documentation":"The declared sentinel ErrIsNotAllowedToHost in server/internal/websocket/handler/control.go is returned by controlRelease (and reachable via controlRequest paths) when the session's profile lacks CanHost or private mode is enabled for the session. In private mode, hosting is restricted, and users without the CanHost profile flag may never take or manipulate host control.","triggerScenarios":"Sending a control release/request message from a session where session.Profile().CanHost is false, or where session.PrivateModeEnabled() is true and the session is not permitted to host.","commonSituations":"View-only members attempting to grab control; private-mode rooms where the operator did not grant CanHost to participants; a client UI showing a 'release control' button even when the user never had hosting rights.","solutions":["Grant CanHost: true to the member profile if the user should be able to host.","Disable private mode for the room if hosting should be open to participants.","Have an admin/host perform the release instead of the restricted session.","Hide control buttons client-side when the profile lacks CanHost."],"exampleFix":"// before\nprofile := types.MemberProfile{ CanWatch: true }\n// after\nprofile := types.MemberProfile{ CanWatch: true, CanHost: true }","handlingStrategy":"validation","validationCode":"// client-side, before sending control release/request\nif (!session.profile.canHost || session.privateMode) {\n  console.warn('this session is not allowed to host')\n  return\n}","typeGuard":"function canHost(session) {\n  return session?.profile?.canHost === true\n}","tryCatchPattern":"try {\n  socket.emit('control/release')\n} catch (e) {\n  if (e.message === 'is not allowed to host') hideHostControls()\n}","preventionTips":["Grant CanHost in profiles for users who need control.","Hide host control UI when profile.canHost is false.","Understand private mode restricts hosting regardless of other flags.","Compare errors against the sentinel (errors.Is(err, ErrIsNotAllowedToHost)) server-side."],"tags":["websocket","permissions","host-control"],"backgroundTag":"host-not-allowed","analyzedSha":"b0f01cedea68893e85a3fd852c0521238c285695","analyzedAt":"2026-09-01T10:35:56.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}