channel.member.list returns 'User undefined' when row's data JSON lacks user_id (read schema columns instead) #34

Closed
opened 2026-04-27 17:52:40 +00:00 by sameh-farouk · 0 comments
Member

Symptom

Channel detail panel renders one or more members as "User undefined". Surfaced during dogfooding while testing a viewer_test account in #general.

Root cause

channel.member.list (crates/hero_collab_server/src/handlers/channel.rs::member_list) read user_id and channel_id ONLY from the JSON cm.data blob. Those fields are also schema columns on channel_members (the PK is (channel_id, user_id) with FK to users.id), but the handler ignored them and trusted the data blob.

When a channel_members.data row was ever written without those fields properly serialised — buggy migration, manual SQL, or a test fixture — the response carried no user_id, and the client's member.user_id-keyed lookups fell through to the "User undefined" / "Unknown" fallbacks at chat-app.js:3121 and :3817.

The specific corrupted row in this case was a test fixture I inserted during canvas read-only testing:

INSERT OR IGNORE INTO channel_members (channel_id, user_id, data)
VALUES (2, 2, json_object('role','member','joined_at',datetime('now')));

The data JSON omitted user_id/channel_id, exposing the latent fragility.

Why the schema column is the right source

  • channel_members.user_id is part of the primary key. Cannot be NULL.
  • It's a foreign key to users.id. Cannot disagree with the joined user.
  • If a data blob ever DID disagree with the schema column, that's corruption — and the schema column is the answer.

Fix in

PR linked below. Server-side only; the client renderers work correctly once user_id is reliably in the response.

### Symptom Channel detail panel renders one or more members as "User undefined". Surfaced during dogfooding while testing a `viewer_test` account in `#general`. ### Root cause `channel.member.list` (`crates/hero_collab_server/src/handlers/channel.rs::member_list`) read `user_id` and `channel_id` ONLY from the JSON `cm.data` blob. Those fields are also schema columns on `channel_members` (the PK is `(channel_id, user_id)` with FK to `users.id`), but the handler ignored them and trusted the data blob. When a `channel_members.data` row was ever written without those fields properly serialised — buggy migration, manual SQL, or a test fixture — the response carried no `user_id`, and the client's `member.user_id`-keyed lookups fell through to the "User undefined" / "Unknown" fallbacks at chat-app.js:3121 and :3817. The specific corrupted row in this case was a test fixture I inserted during canvas read-only testing: ```sql INSERT OR IGNORE INTO channel_members (channel_id, user_id, data) VALUES (2, 2, json_object('role','member','joined_at',datetime('now'))); ``` The `data` JSON omitted `user_id`/`channel_id`, exposing the latent fragility. ### Why the schema column is the right source - `channel_members.user_id` is part of the primary key. Cannot be NULL. - It's a foreign key to `users.id`. Cannot disagree with the joined user. - If a `data` blob ever DID disagree with the schema column, that's corruption — and the schema column is the answer. ### Fix in PR linked below. Server-side only; the client renderers work correctly once `user_id` is reliably in the response.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_collab#34
No description provided.