ppy/osu · error · ChannelNotFoundException
A channel with the name {channelName} could not be found.
Error message
A channel with the name {channelName} could not be found. What it means
Thrown by ChannelManager.OpenChannel when no channel in AvailableChannels matches the requested name. It performs a FirstOrDefault by Name and throws ChannelNotFoundException(name) on miss. Documented via <exception cref="ChannelNotFoundException">. This is the join-path for already-known public channels, not the API join path.
Source
Thrown at osu.Game/Online/Chat/ChannelManager.cs:157
foreach (var joinedChannel in joinedChannels)
joinedChannel.Joined.Value = false;
joinedChannels.Clear();
// additionally clear the history of last joined channels so that the new user can't reopen the old user's channels
// (would likely fail web-side on perms anyway, but why even get that far)
closedChannels.Clear();
}
/// <summary>
/// Opens a channel or switches to the channel if already opened.
/// </summary>
/// <exception cref="ChannelNotFoundException">If the name of the specifed channel was not found this exception will be thrown.</exception>
/// <param name="name"></param>
public void OpenChannel(string name)
{
ArgumentNullException.ThrowIfNull(name);
CurrentChannel.Value = AvailableChannels.FirstOrDefault(c => c.Name == name) ?? throw new ChannelNotFoundException(name);
}
/// <summary>
/// Opens a new private channel.
/// </summary>
/// <param name="user">The user the private channel is opened with.</param>
public void OpenPrivateChannel(APIUser user)
{
ArgumentNullException.ThrowIfNull(user);
if (user.Id == api.LocalUser.Value.Id)
return;
CurrentChannel.Value = JoinedChannels.FirstOrDefault(c => c.Type == ChannelType.PM && c.Users.Count == 1 && c.Users.Any(u => u.Id == user.Id))
?? JoinChannel(new Channel(user));
}
private void currentChannelChanged(ValueChangedEvent<Channel> channel)
View on GitHub (pinned to d9c73e12ad)
Solutions
- Check AvailableChannels.FirstOrDefault(c => c.Name == name) before calling OpenChannel, and fall back to JoinChannel or a server lookup if absent.
- Ensure the channel list has been populated (API request completed) before invoking OpenChannel from external triggers.
- For user-supplied names, validate existence and surface a user-friendly 'channel not found' message instead of propagating the exception.
Example fix
// before
channelManager.OpenChannel("#somechannel"); // throws if not in AvailableChannels
// after
var channel = channelManager.AvailableChannels.FirstOrDefault(c => c.Name == name);
if (channel != null)
channelManager.CurrentChannel.Value = channel;
else
Notifications.Post(new SimpleNotification { Text = $"Channel '{name}' was not found." }); Defensive patterns
Strategy: validation
Validate before calling
var channel = channelManager.AvailableChannels.FirstOrDefault(c => c.Name == name);
if (channel == null) { /* notify 'channel not found' or request server join */ return; }
channelManager.CurrentChannel.Value = channel; Type guard
static bool ChannelIsAvailable(ChannelManager cm, string name)
=> cm.AvailableChannels.Any(c => c.Name == name); Try / catch
try { channelManager.OpenChannel(name); }
catch (ChannelNotFoundException) { /* fall back to JoinChannel or show 'not found' */ } Prevention
- Populate/await the AvailableChannels list before auto-opening channels from deep links.
- For PM channels, use OpenPrivateChannel(user), not OpenChannel(name).
- Validate user-supplied channel names and surface friendly errors.
When it happens
Trigger: Calling OpenChannel(name) with a channel name that isn't currently in AvailableChannels — e.g. a channel that hasn't been fetched/joined, a typo, or a channel the server hasn't returned. Only pre-existing AvailableChannels are searched; it does not query the server.
Common situations: Deep links or commands opening a channel by name before the channel list has loaded; reopening a channel after it was closed/removed; typos in chat commands; trying to open a private/PM channel via OpenChannel (PMs go through OpenPrivateChannel).
Related errors
- Provided client ID must be an integer.
- Can't have zero or fewer stages.
- No valid beatmap files found in the beatmap archive.
- {setInfo.GetDisplayString()} already has a difficulty with t
- {Path} is not a valid archive
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/3387c187335d4bb2.
Report an issue: GitHub.