fullstackhero/dotnet-starter-kit · warning · CustomException

Cannot DM yourself.

Error message

Cannot DM yourself.

What it means

FindOrCreateDmCommandHandler rejects a DM creation request whose participant list includes the calling user themself. DMs in this module are always between distinct users, so including your own id yields a BadRequest CustomException. The check is an ordinal string comparison against the current user's id.

Solutions

  1. Filter the current user's id out of UserIds on the client before calling the API.
  2. Show a self-DM option only via the dedicated self-note flow if one exists, never through this endpoint.
  3. Server-side: keep this guard — optionally return a clearer 400 payload naming the offending id.

Example fix

// before
await api.post('/channels/dm', { userIds: [me.id, other.id] });
// after
const others = [...new Set(targets)].filter(id => id !== me.id);
if (others.length === 0) throw new Error('Cannot start a DM with yourself.');
await api.post('/channels/dm', { userIds: others });
Defensive patterns

Strategy: validation

Validate before calling

const others = [...new Set(userIds)].filter(id => id !== currentUserId);
if (others.length === 0) throw new Error('Cannot DM yourself.');

Type guard

const isSelfDm = (ids: string[], me: string) => ids.some(id => id === me);

Prevention

When it happens

Trigger: Calling POST find-or-create-DM (POST /channels/dm) with cmd.UserIds containing the authenticated user's own id string (exact ordinal match, e.g. the id returned by /users/me passed back verbatim).

Common situations: Frontend pre-selecting the current user in a 'new conversation' multi-select; a 'message user' button rendered on your own profile page; ids compared with different casing via case-insensitive comparisons elsewhere leading devs to think a duplicate won't match.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Modules/Chat/Modules.Chat/Features/v1/Channels/FindOrCreateDm/FindOrCreateDmCommandHandler.cs:30

namespace FSH.Modules.Chat.Features.v1.Channels.FindOrCreateDm;

public sealed class FindOrCreateDmCommandHandler(
    ChatDbContext db,
    IHubContext<AppHub> hub,
    ICurrentUser currentUser)
    : ICommandHandler<FindOrCreateDmCommand, Guid>
{
    public async ValueTask<Guid> Handle(FindOrCreateDmCommand cmd, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(cmd);
        var userId = currentUser.GetUserId();
        if (userId == Guid.Empty) throw new UnauthorizedException("no current user");
        var currentUserId = userId.ToString();

        var otherIds = cmd.UserIds.Distinct(StringComparer.Ordinal).ToList();
        if (otherIds.Any(id => string.Equals(id, currentUserId, StringComparison.Ordinal)))
        {
            throw new CustomException("Cannot DM yourself.", (IEnumerable<string>?)null, System.Net.HttpStatusCode.BadRequest);
        }

        if (otherIds.Count == 1)
        {
            // Two-person DM — deterministic lookup via DirectKey.
            var (lo, hi) = string.CompareOrdinal(currentUserId, otherIds[0]) < 0
                ? (currentUserId, otherIds[0])
                : (otherIds[0], currentUserId);
            var directKey = $"{lo}:{hi}";

            var existing = await db.Channels
                .FirstOrDefaultAsync(c => c.Type == ChannelType.DirectMessage && c.DirectKey == directKey, cancellationToken)
                .ConfigureAwait(false);
            if (existing is not null) return existing.Id;

            var dm = ChatChannel.CreateDirect(currentUserId, otherIds[0]);
            db.Channels.Add(dm);
            await db.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

View on GitHub (pinned to 3f2959e683)