discourse/discourse · error · PresenceChannel::InvalidAccess
invalid access
Error message
invalid access
What it means
Raised in PresenceChannel#present (and related entry paths) as Discourse::InvalidAccess when PresenceChannel#can_enter? returns false for the user — the channel's configuration (public, allowed groups, allowed user ids) does not permit that user to mark presence in /presence/<name>. Authorization failure for the presence channel, not a transient error.
Solutions
- Check the channel's PresenceChannel::Config: public? flag, allowed_user_ids, and allowed_group_ids
- Add the user (or their group) to the channel configuration if access is intended
- Ensure the client is authenticated — anonymous user_ids are always denied
- Rescue Discourse::InvalidAccess in the presence controller and return 403
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at lib/presence_channel.rb:133 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of discourse/discourse@1b2d7253e8 (2026-08-26).
Data as JSON: /api/errors/eccda19bf8f29cc7.
Report an issue: GitHub.
Appendix: source
Thrown at lib/presence_channel.rb:133
end
group_ids ||= GroupUser.where(user_id: user_id).pluck("group_id")
return true if (group_ids & config.allowed_group_ids).present?
end
false
end
# Is a user allowed to enter this channel?
# Currently equal to the can_view? permission
def can_enter?(user_id: nil, group_ids: nil)
return false if user_id.nil?
can_view?(user_id: user_id, group_ids: group_ids)
end
# Mark a user's client as present in this channel. The client_id should be unique per
# browser tab. This method should be called repeatedly (at least once every DEFAULT_TIMEOUT)
# while the user is present in the channel.
def present(user_id:, client_id:)
raise PresenceChannel::InvalidAccess if !can_enter?(user_id: user_id)
mutex_value = SecureRandom.hex
result =
retry_on_mutex_error do
PresenceChannel.redis_eval(
:present,
redis_keys,
[name, user_id, client_id, (Time.zone.now + timeout).to_i, mutex_value],
)
end
if result == 1
begin
publish_message(entering_user_ids: [user_id])
ensure
release_mutex(mutex_value)
end
endView on GitHub (pinned to 1b2d7253e8)