discourse/discourse · error · Discourse::InvalidAccess
access denied
Error message
access denied
What it means
A guard in Search#initialize raising Discourse::InvalidAccess with the generic 'access denied' message when the search context or options (e.g. searching private messages, or an @user / search context the guardian may not inspect) imply access the acting user's Guardian does not grant. The at-fault input is the combination of search term/context/options supplied to Search.new.
Solutions
- Log in — several search contexts (PMs, user-scoped searches) require an authenticated guardian
- Remove the in:messages / private-messages filters or @user context unless you have permission to see them
- Check category security and can_see_private_messages? for the acting user
- Rescue Discourse::InvalidAccess and return an empty or 403 result rather than leaking visibility
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at lib/search.rb:283 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
AI-assisted analysis of discourse/discourse@1b2d7253e8 (2026-08-26).
Data as JSON: /api/errors/d76d06ec42e94909.
Report an issue: GitHub.
Appendix: source
Thrown at lib/search.rb:283
term = process_advanced_search!(term)
if !@order &&
SiteSetting.search_default_sort_order !=
SearchSortOrderSiteSetting.value_from_id(:relevance)
@order = SearchSortOrderSiteSetting.id_from_value(SiteSetting.search_default_sort_order)
end
if term.present?
@term = Search.prepare_data(term, Topic === @search_context ? :topic : nil)
@original_term = Search.escape_string(@term)
end
if @search_pms || @search_all_pms || @opts[:type_filter] == "private_messages"
@opts[:type_filter] = "private_messages"
@search_context ||= @guardian.user
unless @search_context.present? && @guardian.can_see_private_messages?(@search_context.id)
raise Discourse::InvalidAccess.new
end
end
@opts[:type_filter] = "all_topics" if @search_all_topics && @guardian.user
@results =
GroupedSearchResults.new(
type_filter: @opts[:type_filter],
term: clean_term,
blurb_term: term,
search_context: @search_context,
blurb_length: @blurb_length,
is_header_search: !use_full_page_limit,
can_lazy_load_categories: @guardian.can_lazy_load_categories?,
)
end
def limitView on GitHub (pinned to 1b2d7253e8)