Custom Topic Filters: URL Params Not Reaching `TopicQuery.options`

Progress Report so far:

  1. Confirmed that static TopicQuery whitelisting methods like add_custom_param_handler or extra_options_whitelist are not available as class methods in my Discourse version, so those approaches were abandoned.

  2. Implemented a patch for ListController#build_topic_list_options to inject my custom URL parameters (e.g., market_item_statuses, market_price_min) into the opts hash before TopicQuery.new is called.

  3. This part is now working! When I make a request like /c/market/5/l/latest.json?filter=default&market_item_statuses=Available, my server logs confirm the injection:

    [TecencMarket_ListControllerExt_BuildOptsV3] Injected into opts: market_item_statuses = Available
    
    

    So, TopicQuery.new(user, opts) is now receiving opts containing my custom parameters.

Current Sticking Point: 500 Error & Filter Block Not Reached

Despite the parameters now being correctly passed to TopicQuery’s initializer, I still get a 500 Internal Server Error when the request includes these custom market parameters.

To isolate this, I simplified my TopicQuery.add_custom_filter(:"tecenc_market_filters") block to the absolute minimum.

# plugin.rb - Current simplified custom filter block
if ::TopicQuery.respond_to?(:add_custom_filter)
  ::TopicQuery.add_custom_filter(:"tecenc_market_filters") do |topics, topic_query|
    original_topics_relation = topics 
    opts = topic_query.options
    log_prefix_query = "[TecencMarket_SimplifiedFilter_V1.1_Test]" # My debug prefix

    Rails.logger.info "#{log_prefix_query} Opts received by TopicQuery: #{opts.inspect}"

    if opts[:market_item_statuses].present?
      Rails.logger.info "#{log_prefix_query} 'market_item_statuses' IS PRESENT in opts: #{opts[:market_item_statuses]}"
    else
      Rails.logger.info "#{log_prefix_query} 'market_item_statuses' IS NOT PRESENT in opts."
    end
    
    Rails.logger.info "#{log_prefix_query} Returning original topics relation."
    original_topics_relation # Implicit return
  end
  Rails.logger.info "[TecencMarket] Applied SIMPLIFIED custom filter (V1.1_Test)."
end

Observations with this Simplified Filter:

  • Requests without my custom filter parameter (e.g., just /c/market/5/l/latest.json?filter=default):

    • The simplified filter block logs correctly:

      [TecencMarket_SimplifiedFilter_V1.1_Test] Opts received by TopicQuery: {:category=>5, :filter=>"default", ...}
      [TecencMarket_SimplifiedFilter_V1.1_Test] 'market_item_statuses' IS NOT PRESENT in opts.
      [TecencMarket_SimplifiedFilter_V1.1_Test] Returning original topics relation.
      
      
    • The page loads with a 200 OK.

  • Requests with my custom filter parameter (e.g., /c/market/5/l/latest.json?filter=default&market_item_statuses=Available):

    • The ListController patch log appears: [TecencMarket_ListControllerExt_BuildOptsV3] Injected into opts: market_item_statuses = Available

    • A Completed 500 Internal Server Error in ...ms occurs immediately after.

    • Crucially, NO logs from inside the simplified filter block (no [TecencMarket_SimplifiedFilter_V1.1_Test]... lines) appear for this failing request.

This indicates the 500 error happens after TopicQuery is initialized with the opts hash (which now contains my custom parameters), but before or right as Discourse’s core TopicQuery#apply_custom_filters mechanism tries to execute my registered (and now extremely simple) filter block.

I am having difficulty isolating the specific Ruby exception and full backtrace from development.log that immediately precedes the “Completed 500…” line for the failing requests (the log snippets I’ve gathered show the 500 line itself, but not the detailed error message just before it).

Follow-up Question:

Given that:

  1. Custom parameters are now being successfully injected into TopicQuery.options by the ListController patch.

  2. A 500 error occurs when these custom parameters are present in opts.

  3. This 500 error happens before even an extremely simplified custom filter block (that only logs and returns the original relation) gets to execute its first line of code for the request with custom parameters.

  4. This is on Discourse 3.5.0.beta3-dev.

What could be causing TopicQuery itself, or its apply_custom_filters method, to error out before invoking a registered custom filter block, specifically when the options hash contains these plugin-specific keys? Could the previous LocalJumpError we suspected still be relevant at a lower level in how apply_custom_filters handles the iteration or calling of filter blocks, even if my simplified block is just an implicit return?

Any guidance on what to check next in TopicQuery’s behavior with these kinds of custom options, or advice on how to robustly get the full backtrace for the 500 in this scenario, would be immensely helpful.