fullstackhero/dotnet-starter-kit · error · UnauthorizedException
no current user
Error message
no current user
What it means
FindOrCreateDmCommandHandler throws UnauthorizedException when currentUser.GetUserId() returns Guid.Empty, i.e. no authenticated caller. The DM channel is created between the current user and the given users, so identity is required before any other validation.
Solutions
- Authenticate the request with a valid bearer token
- Handle 401 by re-authenticating/refreshing before retrying
- In tests, mock ICurrentUser.GetUserId() to return a real Guid
Example fix
// before currentUser.GetUserId().Returns(Guid.Empty); // handler throws // after currentUser.GetUserId().Returns(Guid.NewGuid());
Defensive patterns
Strategy: validation
Validate before calling
var userId = currentUser.GetUserId();
if (userId == Guid.Empty) throw new UnauthorizedException("no current user"); Type guard
bool isAuthenticated = currentUser.GetUserId() != Guid.Empty;
Try / catch
try { await findOrCreateDm(userIds); }
catch (UnauthorizedException) { /* re-authenticate */ }
catch (CustomException) { /* 'Cannot DM yourself.' — filter out own id */ } Prevention
- Attach JWT to DM requests
- Filter the caller's own ID from UserIds before submit (avoids the related 'Cannot DM yourself.' error)
- Stub ICurrentUser with a real Guid in tests
When it happens
Trigger: Calling FindOrCreateDm without a valid JWT, with an expired token, or in tests without a configured ICurrentUser. Note: passing your own ID in UserIds instead raises 'Cannot DM yourself.' (CustomException), not this error.
Common situations: Session expired before opening a DM; missing Authorization header; integration tests without auth setup.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/16a2e0d18a1fee5b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Chat/Modules.Chat/Features/v1/Channels/FindOrCreateDm/FindOrCreateDmCommandHandler.cs:24
using FSH.Modules.Chat.Data;
using FSH.Modules.Chat.Domain;
using Mediator;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
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)View on GitHub (pinned to 3f2959e683)