fullstackhero/dotnet-starter-kit · error · NotFoundException

Users not found

Error message

Users not found: {string.Join(", ", invalidUserIds)}

What it means

After confirming the group exists, the handler intersects command.UserIds with existing user ids and throws NotFoundException naming every missing user. All-or-nothing: no users are added if any id is invalid.

Solutions

  1. Resolve user ids via the users list endpoint in the same tenant before calling
  2. Remove the invalid ids reported in the message and retry with the valid subset
  3. Recreate missing users if the deletion was accidental

Example fix

// before
userIds: ["3f2...", "00000000-0000-0000-0000-000000000000"]
// after
var valid = users.Where(u => u.TenantId == tenant).Select(u => u.Id); // only existing ids
Defensive patterns

Strategy: validation

Validate before calling

var tenantUserIds = (await api.ListUsers()).Select(u => u.Id).ToHashSet();
var invalid = userIds.Where(id => !tenantUserIds.Contains(id)).ToList();

Type guard

static bool AllValid(IEnumerable<string> ids, ISet<string> known) => ids.All(known.Contains);

Prevention

When it happens

Trigger: AddUsersToGroup call where one or more UserIds do not exist in the tenant — deleted users, users from another tenant, or malformed GUIDs.

Common situations: Batching users from an old export after users were deleted; mixing ids across dev/staging databases; sending usernames instead of user ids.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Groups/AddUsersToGroup/AddUsersToGroupCommandHandler.cs:47

        // Validate group exists
        var groupExists = await _dbContext.Groups
            .AnyAsync(g => g.Id == command.GroupId, cancellationToken);

        if (!groupExists)
        {
            throw new NotFoundException($"Group with ID '{command.GroupId}' not found.");
        }

        // Validate user IDs exist
        var existingUserIds = await _dbContext.Users
            .Where(u => command.UserIds.Contains(u.Id))
            .Select(u => u.Id)
            .ToListAsync(cancellationToken);

        var invalidUserIds = command.UserIds.Except(existingUserIds).ToList();
        if (invalidUserIds.Count > 0)
        {
            throw new NotFoundException($"Users not found: {string.Join(", ", invalidUserIds)}");
        }

        // Get existing memberships
        var existingMemberships = await _dbContext.UserGroups
            .Where(ug => ug.GroupId == command.GroupId && command.UserIds.Contains(ug.UserId))
            .Select(ug => ug.UserId)
            .ToListAsync(cancellationToken);

        var alreadyMemberUserIds = existingMemberships.ToList();
        var usersToAdd = command.UserIds.Except(existingMemberships).ToList();

        // Add new memberships
        var currentUserId = _currentUser.GetUserId().ToString();
        foreach (var userId in usersToAdd)
        {
            _dbContext.UserGroups.Add(UserGroup.Create(userId, command.GroupId, currentUserId));
        }

View on GitHub (pinned to 3f2959e683)