fullstackhero/dotnet-starter-kit · error · UnauthorizedException
no current user
Error message
no current user
What it means
PinMessageCommandHandler throws UnauthorizedException('no current user') when currentUser.GetUserId() returns Guid.Empty, meaning the request carried no authenticated identity. This is the library's 401 path, thrown before any message lookup.
Solutions
- Refresh/acquire a valid access token and send it with the request
- Verify JWT bearer options and that authentication runs before authorization
- Seed an ICurrentUser in test harnesses calling handlers directly
- Confirm the client attaches the Authorization header on mutation calls
Defensive patterns
Strategy: try-catch
Validate before calling
if (!auth.isAuthenticated()) await auth.login();
Type guard
function canPin(user: { Id: string } | null): boolean { return user !== null && user.Id !== '00000000-0000-0000-0000-000000000000'; } Try / catch
try { await pinMessage(messageId); }
catch (e) { if (isUnauthorized(e)) { await auth.refresh(); return pinMessage(messageId); } throw e; } Prevention
- Disable pin actions when logged out
- Refresh token before mutations
- Send Authorization header on every mutation
- Seed ICurrentUser in handler tests
When it happens
Trigger: Pinning a message without a valid JWT; missing/expired/invalid bearer token.
Common situations: Expired token not refreshed in the client, raw handler invocation in tests without a current user, or auth middleware misconfiguration.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/7bae0bfc9b8d8973.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Chat/Modules.Chat/Features/v1/Messages/PinMessage/PinMessageCommandHandler.cs:23
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.Messages.PinMessage;
public sealed class PinMessageCommandHandler(
ChatDbContext db,
ICurrentUser currentUser,
IHubContext<AppHub> hub)
: ICommandHandler<PinMessageCommand, Unit>
{
public async ValueTask<Unit> Handle(PinMessageCommand 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 message = await db.Messages.FirstOrDefaultAsync(m => m.Id == cmd.MessageId, cancellationToken)
.ConfigureAwait(false)
?? throw new NotFoundException("Message not found.");
var channel = await db.Channels.FirstOrDefaultAsync(c => c.Id == message.ChannelId, cancellationToken)
.ConfigureAwait(false)
?? throw new NotFoundException("Message not found.");
channel.RequireMember(currentUserId);
message.Pin(currentUserId);
await db.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
await hub.Clients.Group($"channel:{channel.Id}")
.SendAsync("ChatMessagePinned", message.ToDto(), cancellationToken)
.ConfigureAwait(false);
return Unit.Value;View on GitHub (pinned to 3f2959e683)