fullstackhero/dotnet-starter-kit · error · ArgumentException

All user ids must be non-empty.

Error message

All user ids must be non-empty.

What it means

CreateGroupDm validates every entry in userIds with string.IsNullOrWhiteSpace; any blank/null/whitespace member id throws ArgumentException(nameof(userIds)). The member list must be fully populated with real user identifiers.

Solutions

  1. Filter before calling: userIds = ids.Where(id => !string.IsNullOrWhiteSpace(id)).ToList().
  2. Validate every member id client-side before submitting the creation form.
  3. Trim inputs and drop empty rows from dynamic member pickers.
  4. Fix deserialization that splits on separators without removing empty entries.

Example fix

// before
var channel = ChatChannel.CreateGroupDm(rawIds, currentUserId);
// after
var ids = rawIds.Where(id => !string.IsNullOrWhiteSpace(id)).Distinct().ToList();
if (ids.Count < 3) throw new ValidationException("At least 3 valid members required");
var channel = ChatChannel.CreateGroupDm(ids, currentUserId);
Defensive patterns

Strategy: validation

Validate before calling

var clean = userIds.Where(id => !string.IsNullOrWhiteSpace(id)).Distinct().ToList();
if (clean.Count < 3) throw new ValidationException("Need 3+ non-empty member ids");

Type guard

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

Try / catch

try { var c = ChatChannel.CreateGroupDm(userIds, creatorId); }
catch (ArgumentException ex) when (ex.ParamName == nameof(userIds) && ex.Message.Contains("non-empty"))
{ return Results.BadRequest("All member ids must be non-empty"); }

Prevention

When it happens

Trigger: CreateGroupDm called with a userIds array containing null, "", or whitespace strings — typically an array pre-allocated to a fixed size but only partially filled, or placeholder entries from an unvalidated form.

Common situations: Frontend submits empty rows from an 'add member' input list; deserialization of a comma-separated string with trailing separators; test data with empty strings as stand-in user ids.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

        };
        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
                : ChannelMemberRole.Member;
            c._members.Add(ChannelMember.Create(c.Id, uid, role));
        }
        c.AddDomainEvent(DomainEvent.Create((id, ts) =>

View on GitHub (pinned to 3f2959e683)