apache / apache/solr-mcp

search: ClassCastException when a facet returns zero buckets

Closed
#182 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.