search: ClassCastException when a facet returns zero buckets
- Dominant language
- Java
- Stars
- 19
- Forks
- 17
- Avg merge
- 11d 14h
- Merged PRs (30d)
- 6
Description
## 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**
```json
{"collection": "shows", "query": "*:*", "facetFields": ["platform"], "rows": 0}
```
```
{"numFound":61,...,"facets":{"platform":{"Netflix":20,"HBO Max":7,...}}}
```
**B — same field, filter matches nothing → throws**
```json
{"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**:
```json
"facet_counts": { "facet_fields": { "platform": [] } }
```
`JsonResponseParser.isFlatNamedList` rejects zero-length arrays
([`JsonResponseParser.java:157`](https://github.com/apache/solr-mcp/blob/main/src/main/java/org/apache/solr/mcp/server/config/JsonResponseParser.java#L157)):
```java
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:
```json
"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
Contributor guide
Research direction
Start with JsonResponseParser.java, especially isFlatNamedList and the conversion path described in the report, then trace how search requests set Solr response parameters. Reproduce the supplied zero-match facet query over Solr 9 and verify that requesting json.nl=map makes empty facet_fields parse as NamedList and return an empty result instead of throwing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- search
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100