fullstackhero/dotnet-starter-kit · error · ArgumentException

Group DM requires at least 3 distinct members.

Error message

Group DM requires at least 3 distinct members.

What it means

ChatChannel.CreateGroupDm requires the userIds list to contain at least 3 entries; a shorter list throws ArgumentException(nameof(userIds)). Group DMs are by definition 3+ distinct participants, distinct from 1:1 DMs and named Channels.

Solutions

  1. Use ChatChannel.CreateDirect for exactly two participants; reserve CreateGroupDm for 3+.
  2. Validate userIds.Count >= 3 in the endpoint/handler before calling the factory.
  3. Enforce a minimum member count (3) in the group-creation UI form.
  4. Check client code that may truncate the selection array before sending.

Example fix

// before
var channel = ChatChannel.CreateGroupDm(selectedIds, currentUserId);
// after
if (selectedIds.Count == 2)
    return ChatChannel.CreateDirect(selectedIds[0], selectedIds[1]);
if (selectedIds.Count < 3)
    throw new ValidationException("Group DM needs at least 3 members");
var channel = ChatChannel.CreateGroupDm(selectedIds, currentUserId);
Defensive patterns

Strategy: validation

Validate before calling

// before calling the factory
var ids = userIds?.Where(id => !string.IsNullOrWhiteSpace(id)).Distinct().ToList()
          ?? throw new ValidationException("userIds required");
if (ids.Count < 3)
    throw new ValidationException("Group DM requires at least 3 members");

Type guard

bool IsValidGroupDm(IReadOnlyList<string>? ids) =>
    ids is not null && ids.Count >= 3 && ids.All(id => !string.IsNullOrWhiteSpace(id));

Try / catch

try { var c = ChatChannel.CreateGroupDm(userIds, creatorId); }
catch (ArgumentException ex) when (ex.ParamName == nameof(userIds)) { return Results.BadRequest(ex.Message); }

Prevention

When it happens

Trigger: CreateGroupDm(userIds, creatorUserId) called with userIds.Count < 3 — e.g. forwarding a 2-element selection to the group-DM factory, or an empty/defaulted list when the user skips member selection.

Common situations: Frontend lets users submit a 'group' with only 2 picks (should use CreateDirect instead); batch script building channels with placeholder member arrays; migration code mapping old 2-person rooms into GroupMessage type.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/3b790dd26b2873f4. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Chat/Modules.Chat/Domain/ChatChannel.cs:121

            IsPrivate = true,
            DirectKey = $"{lo}:{hi}",
            CreatedByUserId = userAId,
            CreatedAtUtc = DateTime.UtcNow,
        };
        c._members.Add(ChannelMember.Create(c.Id, userAId, ChannelMemberRole.Member));
        c._members.Add(ChannelMember.Create(c.Id, userBId, ChannelMemberRole.Member));
        c.AddDomainEvent(DomainEvent.Create((id, ts) =>
            new ChannelCreatedDomainEvent(c.Id, c.Type, null, userAId, id, ts)));
        return c;
    }

    public static ChatChannel CreateGroupDm(IReadOnlyList<string> userIds, string creatorUserId)
    {
        ArgumentNullException.ThrowIfNull(userIds);
        ArgumentException.ThrowIfNullOrWhiteSpace(creatorUserId);
        if (userIds.Count < 3)
        {
            throw new ArgumentException("Group DM requires at least 3 distinct members.", nameof(userIds));
        }
        if (userIds.Any(string.IsNullOrWhiteSpace))
        {
            throw new ArgumentException("All user ids must be non-empty.", nameof(userIds));
        }

        var c = new ChatChannel
        {
            Id = Guid.CreateVersion7(),
            Type = ChannelType.GroupMessage,
            IsPrivate = true,
            CreatedByUserId = creatorUserId,
            CreatedAtUtc = DateTime.UtcNow,
        };
        foreach (var uid in userIds.Distinct(StringComparer.Ordinal))
        {
            var role = string.Equals(uid, creatorUserId, StringComparison.Ordinal)
                ? ChannelMemberRole.Admin

View on GitHub (pinned to 3f2959e683)