fullstackhero/dotnet-starter-kit · error · UnauthorizedException
no current user
Error message
no current user
What it means
AddChannelMembersCommandHandler rejects the command with UnauthorizedException when currentUser.GetUserId() returns Guid.Empty, meaning no authenticated user is associated with the request context. The handler needs a current user to attribute the membership change and run permission checks.
Solutions
- Ensure the request carries a valid, non-expired JWT bearer token
- Check authentication/401 handling at the client and re-login on token expiry
- In tests, mock ICurrentUser.GetUserId() to return a real Guid or use the authenticated test client
Example fix
// before (test) var handler = new AddChannelMembersCommandHandler(db, currentUserSubstitute); // GetUserId -> Guid.Empty // after currentUserSubstitute.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 handler.Handle(cmd, ct); }
catch (UnauthorizedException) { /* return 401 / trigger re-login */ } Prevention
- Always send Authorization header
- Refresh tokens before expiry
- In tests, stub ICurrentUser with a real Guid
When it happens
Trigger: Invoking the AddChannelMembers endpoint without a valid JWT, with an expired/anonymous identity, or in tests without a mocked ICurrentUser returning a real Guid.
Common situations: Missing/invalid Authorization header; token expired; integration tests forgetting to authenticate the request; calling the handler directly with an unconfigured ICurrentUser substitute.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/1c81fa964bdc60bb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Chat/Modules.Chat/Features/v1/Channels/AddChannelMembers/AddChannelMembersCommandHandler.cs:24
using FSH.Modules.Chat.Data;
using FSH.Modules.Chat.Features.v1.Internal;
using Mediator;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace FSH.Modules.Chat.Features.v1.Channels.AddChannelMembers;
public sealed class AddChannelMembersCommandHandler(
ChatDbContext db,
ICurrentUser currentUser,
IHubContext<AppHub> hub)
: ICommandHandler<AddChannelMembersCommand, Unit>
{
public async ValueTask<Unit> Handle(AddChannelMembersCommand 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 channel = await db.Channels.FirstOrDefaultAsync(c => c.Id == cmd.ChannelId, cancellationToken)
.ConfigureAwait(false)
?? throw new NotFoundException("Channel not found.");
// Members can invite to public channels they belong to; private channels require Admin.
var caller = channel.RequireMember(currentUserId);
if (channel.IsPrivate && caller.Role != ChannelMemberRole.Admin)
{
throw new ForbiddenException("Only channel admins can add members to private channels.");
}
var newlyAdded = new List<string>();
foreach (var uid in cmd.UserIds.Distinct(StringComparer.Ordinal))
{
// Skip duplicates silently — endpoint is idempotent for already-members.
if (channel.Members.Any(m => string.Equals(m.UserId, uid, StringComparison.Ordinal))) continue;View on GitHub (pinned to 3f2959e683)