Bug Fix: Fixed TypeError on streams table load after container restart: Added robust data validation and type coercion to handle malformed filter options during container startup. The streams table MultiSelect components now safely convert group names to strings and filter out null/undefined values, preventing "right-hand side of 'in' should be an object, got number" errors when the backend hasn't fully initialized. API error handling returns safe defaults.

This commit is contained in:
SergeantPanda 2026-01-18 16:24:26 -06:00
parent 620d65d1de
commit 39bf57bf40
3 changed files with 20 additions and 7 deletions

View file

@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed TypeError on streams table load after container restart: Added robust data validation and type coercion to handle malformed filter options during container startup. The streams table MultiSelect components now safely convert group names to strings and filter out null/undefined values, preventing "right-hand side of 'in' should be an object, got number" errors when the backend hasn't fully initialized. API error handling returns safe defaults.
- Fixed XtreamCodes API crash when channels have NULL channel_group: The `player_api.php` endpoint (`xc_get_live_streams`) now gracefully handles channels without an assigned channel_group by dynamically looking up and assigning them to "Default Group" instead of crashing with AttributeError. Additionally, the Channel serializer now auto-assigns new channels to "Default Group" when `channel_group_id` is omitted during creation, preventing future NULL channel_group issues.
- Fixed streams table column header overflow: Implemented fixed-height column headers (30px max-height) with pill-style filter display showing first selection plus count (e.g., "Sport +3"). Prevents header expansion when multiple filters are selected, maintaining compact table layout. (Fixes #613)
- Fixed VOD logo cleanup button count: The "Cleanup Unused" button now displays the total count of all unused logos across all pages instead of only counting unused logos on the current page.

View file

@ -783,6 +783,8 @@ export default class API {
return response;
} catch (e) {
errorNotification('Failed to retrieve filter options', e);
// Return safe defaults to prevent crashes during container startup
return { groups: [], m3u_accounts: [] };
}
}

View file

@ -440,13 +440,23 @@ const StreamsTable = ({ onReady }) => {
setAllRowIds(ids);
// Set filtered options based on current filters
setGroupOptions(filterOptions.groups);
setM3uOptions(
filterOptions.m3u_accounts.map((m3u) => ({
label: m3u.name,
value: `${m3u.id}`,
}))
);
// Ensure groupOptions is always an array of valid strings
if (filterOptions && typeof filterOptions === 'object') {
setGroupOptions(
(filterOptions.groups || [])
.filter((group) => group != null && group !== '')
.map((group) => String(group))
);
// Ensure m3uOptions is always an array of valid objects
setM3uOptions(
(filterOptions.m3u_accounts || [])
.filter((m3u) => m3u && m3u.id != null && m3u.name)
.map((m3u) => ({
label: String(m3u.name),
value: String(m3u.id),
}))
);
}
if (initialDataCount === null) {
setInitialDataCount(result.count);