Found while implementing objectui#8459 and left deliberately unfixed there. Filed unassigned, ⛔ not claimed.
What objectui#8459 fixed, and the gap it does not close
objectui#8459 / PR #8476 converged RelatedList's cell placeholder onto isValueEmpty, the same predicate pruneEmpty uses, so a surviving whitespace-only or empty-array cell now draws the muted em-dash instead of painting blank.
That fix lives inside makeCell. But makeCell opens with:
const makeCell = (key: string, def: any): ((value: any) => any) | undefined => {
if (!def?.type) return undefined;
const rendererType = resolveCellRendererType({ type: def.type, format: def.format }) || def.type;
const CellRenderer = getCellRenderer(rendererType);
if (!CellRenderer) return undefined;
When it returns undefined the column gets no cell function at all, so the data-table renders the raw row value and the placeholder branch — fixed or not — never runs. pruneEmpty still judges that column with the full isValueEmpty, so the two spellings go on disagreeing on exactly this path.
Measured
Explicit columns: [{accessorKey:'product'}, {accessorKey:'memo'}] where memo is not declared in the object schema (so fieldDef is undefined), against claude/issue-8459-relatedlist-emptiness with the objectui#8459 fix applied:
heads: ["Product","Memo"]
rows: [["Widget"," "], ["Gadget","real memo"]]
The Memo column survives (one row has a value), and the whitespace-only cell renders " " — a visually blank cell, the same defect objectui#8459 closed for typed columns.
How it is reached
Any column whose accessor does not resolve to a schema field with a type:
- a page author passing
columns: ['some_key'] for a key the child object's schema does not declare (or declares without a type);
- a column surviving against data whose shape has drifted from the schema.
Both are author-side mistakes in a sense, but the failure is silent and the renderer already chose to render something for them, so "blank vs em-dash" is still this component's call.
Why it was not fixed in objectui#8459
Attaching a cell to columns that deliberately have none is a different mechanism, not a widening of an existing predicate: it changes rendering for every untyped column, including ones currently rendering raw objects as [object Object]. That is a new verification surface and a behaviour change well outside a card scoped to "the two spellings must stop disagreeing", so it was measured and reported rather than ridden in.
Suggested shape (not settled)
Either give the no-renderer path a minimal cell that answers isValueEmpty and otherwise renders the raw value unchanged, or decide explicitly that untyped columns are outside the placeholder contract and say so at the return undefined. The first keeps one definition of emptiness for the whole grid; the second at least stops the disagreement being accidental.
⚠️ If it is fixed, the pin belongs with the objectui#8459 cases and must assert the rendered outcome with a by-value control, and stay green for an untyped column holding a real value.
Dedup
Searched objectstack-ai/objectui via MCP search_issues (REST is 403 from the dev container): RelatedList two emptiness spellings disagree pruneEmpty makeCell, which returned objectui#8459 as a control hit so the reading is real. Nothing covers the untyped-column path.
Found while implementing objectui#8459 and left deliberately unfixed there. Filed unassigned, ⛔ not claimed.
What objectui#8459 fixed, and the gap it does not close
objectui#8459 / PR #8476 converged
RelatedList's cell placeholder ontoisValueEmpty, the same predicatepruneEmptyuses, so a surviving whitespace-only or empty-array cell now draws the muted em-dash instead of painting blank.That fix lives inside
makeCell. ButmakeCellopens with:When it returns
undefinedthe column gets nocellfunction at all, so the data-table renders the raw row value and the placeholder branch — fixed or not — never runs.pruneEmptystill judges that column with the fullisValueEmpty, so the two spellings go on disagreeing on exactly this path.Measured
Explicit
columns: [{accessorKey:'product'}, {accessorKey:'memo'}]wherememois not declared in the object schema (sofieldDefisundefined), againstclaude/issue-8459-relatedlist-emptinesswith the objectui#8459 fix applied:The
Memocolumn survives (one row has a value), and the whitespace-only cell renders" "— a visually blank cell, the same defect objectui#8459 closed for typed columns.How it is reached
Any column whose accessor does not resolve to a schema field with a
type:columns: ['some_key']for a key the child object's schema does not declare (or declares without atype);Both are author-side mistakes in a sense, but the failure is silent and the renderer already chose to render something for them, so "blank vs em-dash" is still this component's call.
Why it was not fixed in objectui#8459
Attaching a
cellto columns that deliberately have none is a different mechanism, not a widening of an existing predicate: it changes rendering for every untyped column, including ones currently rendering raw objects as[object Object]. That is a new verification surface and a behaviour change well outside a card scoped to "the two spellings must stop disagreeing", so it was measured and reported rather than ridden in.Suggested shape (not settled)
Either give the no-renderer path a minimal
cellthat answersisValueEmptyand otherwise renders the raw value unchanged, or decide explicitly that untyped columns are outside the placeholder contract and say so at thereturn undefined. The first keeps one definition of emptiness for the whole grid; the second at least stops the disagreement being accidental.Dedup
Searched
objectstack-ai/objectuivia MCPsearch_issues(REST is 403 from the dev container):RelatedList two emptiness spellings disagree pruneEmpty makeCell, which returned objectui#8459 as a control hit so the reading is real. Nothing covers the untyped-column path.