I think that I have found the issue here: tvheadend/tvheadendblob/fa8011b4667df787c4d6c6acfa443dd68d0f13ea/src/epg.c#L2612C1-L2617C2
static int _epg_sort_channel_num_ascending ( const void *a, const void *b, void *eq )
{
int64_t v1 = channel_get_number((*(epg_broadcast_t**)a)->channel);
int64_t v2 = channel_get_number((*(epg_broadcast_t**)b)->channel);
return v1 - v2;
}
This is the sort comparison function that returns a (signed) int to indicate how qsort should process these 2 elements. However, the channel numbers are always stored as int64_t multiplied by 1000000. So, channel '3333' is stored as '3333000000' in the int64_t. This is all fine until the result of v1 - v2 is greater than 231 (2,147,483,648) when an overflow occurs and the qsort function fails. This also explains why channel '333' is OK.
The function _epg_sort_channel_descending will also misbehave due to the same issue.