Skip to content

search: ClassCastException when a facet returns zero buckets #182

Description

@adityamparikh

Summary

Any search call with facetFields that produces zero facet buckets fails with:

class java.util.ArrayList cannot be cast to class org.apache.solr.common.util.NamedList

This is not specific to a field type or a collection — the same field succeeds or fails purely
depending on whether the query matched anything.

Reproduction

Solr 9 in SolrCloud mode, a collection shows with a single-valued string field platform
(docValues on), 61 documents indexed.

A — facet has buckets → works

{"collection": "shows", "query": "*:*", "facetFields": ["platform"], "rows": 0}
{"numFound":61,...,"facets":{"platform":{"Netflix":20,"HBO Max":7,...}}}

B — same field, filter matches nothing → throws

{"collection": "shows", "query": "platform:NoSuchPlatform", "facetFields": ["platform"], "rows": 0}
class java.util.ArrayList cannot be cast to class org.apache.solr.common.util.NamedList

Verified end-to-end over MCP STDIO against a published container image, and independently over
the HTTP transport.

Root cause

Solr serializes an empty facet field as an empty JSON array:

"facet_counts": { "facet_fields": { "platform": [] } }

JsonResponseParser.isFlatNamedList rejects zero-length arrays
(JsonResponseParser.java:157):

int size = arrayNode.size();
if (size == 0 || size % 2 != 0)
    return false;

so convertArray falls through to the plain-list branch and returns an ArrayList. SolrJ's
QueryResponse.getFacetFields() then casts that value to NamedList and throws.

The heuristic cannot be fixed by simply allowing size == 0: a bare [] is genuinely ambiguous
between an empty facet NamedList and an empty plain list, and the parser has no context to tell
them apart.

Suggested fix

Request json.nl=map explicitly rather than relying on Solr's flat default. Facet fields then
arrive as JSON objects:

"facet_fields": { "platform": {"Netflix": 20} }     // non-empty
"facet_fields": { "platform": {} }                   // empty

Both map unambiguously onto NamedList through the existing convertObject path, which removes
the flat-array heuristic and this whole class of ambiguity rather than patching the symptom.

Impact

A user asking a perfectly ordinary question — "break these results down by platform" where the
filter happens to match nothing — gets a raw Java exception instead of an empty result set. Zero
matches is a normal outcome of a search, not an error condition.

Environment

  • main @ a84033b; JsonResponseParser.java unmodified at that commit
  • Solr 9 (solr:9-slim), SolrCloud mode
  • solr-mcp 1.0.0-SNAPSHOT, Spring Boot 3.5.14

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions