Jewelry AI · Model catalogue
An empty model grid is a match result, not a fault
Every filter you set becomes one condition on the request, and each condition is compared with a stored field exactly. A model whose field was left blank cannot match any value, and a combination the catalogue was never tagged for is answered with an empty list rather than a message.
What a filtered request returns
When you narrow the model catalogue, the app asks the server for a list and the server answers with a list. If nothing matches, that list is empty. The empty answer is not an error and carries no reason with it: as far as the response is concerned, a grid with one model in it and a grid with none are the same kind of result.
Each filter you set becomes one condition on that request, and a filter you leave unset adds nothing. This is the whole reason the unfiltered grid is the widest view available: conditions subtract records, they never bring records back. Two filters that each return models on their own can still return nothing together.
Verified in apps/api/src/models/models.service.ts and apps/api/src/models/models.controller.ts in the Elanorya API, read August 2026. The filter clause is written so that the condition exists only when you supply the value, in the form `...(filter.gender ? { gender: filter.gender } : {})`.
What the filter compares
Four properties of the comparison decide what an empty result means.
- The comparison is exact.
- The value you choose is compared with the value stored on the model record. There is no partial match and no fallback to a nearby value, so a record either carries exactly what you asked for or it is not in the answer.
- An empty field on a record matches nothing.
- Category, gender and framing may be absent on a model record (apps/api/src/models/models.service.ts:9-11). A record with one of them empty cannot equal any value you set for that field, so it can appear only while that filter is off. This is a property of the matching rule; how many records are in that state is data the code does not contain.
- No rule compares one filter with another.
- Each field is validated separately by the request schema — framing is accepted as an optional value limited to close or wide (apps/api/src/models/models.controller.ts) — and nothing checks your choices against each other. A combination the catalogue was never tagged for is therefore a well-formed request rather than a rejected one.
- Body region travels with the record but is not a filter.
- Each model record carries a body-region value and sends it to the app (`bodyRegion: string | null;`, apps/api/src/models/models.service.ts), and the server offers no body-region filter, so a request for one body region only cannot be made. Whether the app displays that value was not verified for this page.
Filter behaviour, field by field
The third column describes a record that is complete in every other respect and still leaves the list.
| What you set | How the server matches it | What happens to a record with that field empty |
|---|---|---|
| Category | One condition, compared exactly with the category on the record | It leaves the list for as long as the category filter is applied |
| Gender | One condition, compared exactly with the gender on the record | It leaves the list for as long as the gender filter is applied |
| Framing | One condition, accepted only as close or wide, compared exactly | It leaves the list for as long as the framing filter is applied |
| Body region | Not accepted as a filter; the value is sent with the record | Nothing, because no request can be narrowed by this field |
| Nothing at all | No condition is added to the request | It stays in the list |
Reading a result you did not expect
The screen gives you one signal — the size of the list — so the reading has to come from what you changed.
| Situation | Choose | Why |
|---|---|---|
| The grid empties the moment you add one filter. | Clear that one filter and keep the others. | Each filter is an independent condition, so the one you added last is the one that removed the records. |
| A model you have used before is absent from a filtered view. | Look for it with every filter cleared before concluding it is unavailable. | A record whose field is empty drops out of a filtered list while remaining in the unfiltered one. |
| The model is absent from the unfiltered list as well. | Treat it as no longer listed and choose another model. | A record marked inactive is not returned by the listing at all, and nothing is sent in its place. |
| A category and framing pair returns nothing at any point. | Change one of the two values instead of looking for a fault. | The two fields are never checked against each other, so an untagged pair is answered with an empty list rather than a rejection. |
| You need models of one body region only. | Narrow with the filters that exist and accept that the answer is not restricted by body region. | The server accepts no body-region filter, so that narrowing cannot be requested from this surface. |
Common misreadings of an empty grid
Each of these follows from assuming the empty list is a message about the catalogue rather than the outcome of a comparison.
Reading the empty grid as a broken app and repeating the same request.
The empty list is a completed answer. Changing one filter value tells you more than sending the same request again.
Judging the size of the catalogue from two or three filtered views.
Compare against the unfiltered grid. Every condition can only remove records, so a filtered view is always the smaller picture.
Assuming the request was checked for sense before it ran.
No rule compares your filter fields, so an untagged combination and a set of records with an empty field produce the same empty answer.
Planning a step around a narrowing the request cannot express.
Body region is not part of the filter set, so any plan that depends on asking for one body region has to be rewritten around the filters that exist.
What this page does not settle
The evidence behind this page covers the matching mechanism and nothing beyond it.
- Which category, gender and framing combinations the catalogue actually holds, and which of them return nothing. That lives in catalogue data and platform constants, not in the code that was read.
- How many models exist, or how they are distributed across categories. Those numbers are database values and are not readable from this surface.
- How the filter controls appear in the app: which filters are offered, what their defaults are, and what is drawn when a list comes back empty. None of that was verified here.
- How a model is chosen, validated or rejected while a generation runs. That logic sits elsewhere in the API.
- How model records are created or edited and where their images come from. Only the read path was examined.
Questions
Does the app warn me when a filter combination has no models?
The server answers a request that matches nothing with an empty list and no error, so the absence of an explanation is the expected behaviour rather than a missing warning. What the app draws in place of an empty list was not verified for this page.
Why does a model I saw a moment ago disappear when I add a filter?
A filter is an exact comparison against a stored field. If that field is empty on the model record, the record cannot equal any value you set, so it leaves the list until you clear that filter and returns unchanged afterwards.
Can I ask for hand models only?
No. The model record carries a body-region value and sends it to the app, but the server does not accept body region as a filter, so that narrowing cannot be requested (apps/api/src/models/models.service.ts).
Is a combination that cannot exist rejected before it runs?
No. Each filter field is validated on its own and nothing compares them, so a combination the catalogue was never tagged for is accepted as a valid request and answered with an empty list.