# A screen is empty and should not be

An empty screen has four causes and they look identical. A filter or folder is excluding the rows; the rows carry no workspace stamp and are invisible rather than missing; the path was refused for this session and the screen rendered its empty state; or there is genuinely nothing. Work through them in that order — the first is far commoner than the last.

- **Status:** Available
- **Audience:** both
- **In the app:** #/inbox, #/relationships, #/calls
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/troubleshooting/screen-empty/

## Empty, or not finished?

Before diagnosing anything, separate an empty result from an unfinished one. A screen that is still fetching has not rendered its rows yet, and that initial state looks the same as 'nothing here' to a person watching. Reload once and let it settle; a genuinely empty list stays empty when the loading state has cleared.

## The four causes, in the order to check them

| Cause | Tell | Fix |
|---|---|---|
| A filter, folder or saved view | The count strip disagrees with the list, or another tab has rows | Clear the filter; check the folder and the status separately |
| No workspace stamp | The record exists and can be found by id, but never appears in a list | The row needs its workspace stamp; this is an administrator's fix |
| A refused path | Only one audience sees the emptiness, on the same data | The capability needs a route the customer facade recognises |
| Genuinely nothing | Every filter cleared, both audiences agree, the counts say zero | Nothing to fix |

The folder and the status are different questions, and conflating them is the commonest first cause. The folder says where a conversation sits; the status says what the engine has decided about it. A link somebody saved months ago may carry both, and a folder that is right with a status that is wrong shows nothing at all.

The second cause is the one worth understanding properly. Every scoped record carries a workspace id and is filtered three times — by the allowlist in the middleware, by the ORM kernel, and by row-level security in the database. A row with no stamp passes none of those filters, so it is invisible rather than deleted. It also means a new scoped table needs its row-level security applied in the same release: a table with a workspace column that the kernel does not know about is scoped by nothing at all.

## What Connect completed

The request ran to completion and the screen rendered the answer it was given. Where the cause was a refusal, the refusal was correct — a path a session is not permitted to call is denied by an allowlist rather than half-served — and the isolation guarantees held throughout. Nothing was deleted, and no record was modified by looking at it.

## What Connect did not complete

It did not distinguish the four cases for you. An empty list and a refused request currently look the same on the screen, which is the honest description of the gap: the refusal is recorded, but the person in front of the screen is not told which of the four they are looking at. That is why the order above starts with the cheapest check rather than the most interesting one.

## What you can do

1. Clear every filter, then check the folder and the status separately.
   - Result: If rows appear, you had the first cause and the record was never in doubt.
2. Compare the count strip with the list.
   - Result: Counts that say there are rows while the list shows none is a different problem from counts that also say zero.
3. Confirm which workspace you are in.
   - Result: Every record belongs to exactly one. Looking at the right screen in the wrong workspace produces a perfectly correct empty list.
4. Try the same screen as the other audience if you can.
   - Result: If the Owner sees rows and a customer sees none on the same data, the cause is the path, not the data — and that is worth reporting as such.

## What an administrator can do

- Check whether the record carries a workspace stamp at all. Invisible and missing are different diagnoses with different repairs.
- Check whether the capability has a customer route. Anything the facade does not recognise is refused, and the parity suite records the remaining gaps deliberately so they shrink rather than grow.
- Check that a recently added scoped table is in the kernel's list and has row-level security applied, since the table is created at boot but the security is applied by an operational step.

## When to escalate

Escalate when one audience sees rows and the other does not on identical data, or when a record can be opened directly but never appears in the list it belongs to. The first is a path problem, the second is a stamp problem, and both are invisible from inside a single session. Bring the route, the workspace and which session you were in.

## Questions

### The count says there are twelve and the list shows none. What is that?

Counts and lists can be computed differently, so a disagreement points at the query rather than the data. Report it with the route and the workspace — a count that disagrees with its own list is a defect, not a filter.

### Could a permission make a screen empty rather than showing an error?

Yes, and this is the design: a path a customer session may not call is refused by an allowlist, and the screen renders with nothing rather than a raw error. It is the reason 'works for me' reports are so common between audiences.

### I deleted something and now the whole list is empty.

Deletion here is generally a soft mark on the canonical row rather than removal, so a deleted item disappears from lists without taking anything else with it. An entire list emptying after one deletion is a filter or a workspace question, not a cascade.

## Related

- [A row with no workspace stamp is invisible, not missing](https://connectbyjbrh.com/research/invisible-not-missing/)
- [Data that is invisible rather than missing](https://connectbyjbrh.com/research/workspace-stamp/)
- [A tenant facade that fails closed](https://connectbyjbrh.com/research/closed-by-default-facade/)
- [A screen is slow to load](https://connectbyjbrh.com/docs/troubleshooting/slow-screen/)
- [Security and isolation](https://connectbyjbrh.com/docs/security/)
- [Troubleshooting](https://connectbyjbrh.com/docs/troubleshooting/)

## What this page is based on

- `docs-source/sources/GENERAL.md` §1, §2, §3 — the facade, the kernel, scoped tables
- `backend/app/triage_console.py` — folders, statuses and the count strip
- Connect capability registry (docs-source/facts.py)
