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

  1. Check the channel's PresenceChannel::Config: public? flag, allowed_user_ids, and allowed_group_ids
  2. Add the user (or their group) to the channel configuration if access is intended
  3. Ensure the client is authenticated — anonymous user_ids are always denied
  4. 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
    end

View on GitHub (pinned to 1b2d7253e8)