fullstackhero/dotnet-starter-kit · error · UnauthorizedException
no current user
Error message
no current user
What it means
SendMessageCommandHandler requires an authenticated user before sending a message. It calls ICurrentUser.GetUserId(); when the JWT/context carries no user (or an empty Guid), it throws UnauthorizedException("no current user") instead of attempting to persist a message with no sender.
Solutions
- Ensure the caller sends a valid Bearer token (log in first; refresh if expired).
- Verify UseAuthentication/UseAuthorization ordering in the host pipeline.
- Check that the endpoint requires authorization (no [AllowAnonymous]) and the JWT bearer options (Authority, Audience) are correct.
- If invoked server-side (job/hub), propagate the user's claims/token into the call context.
Example fix
// before
fetch('/api/v1/channels/'+id+'/messages', { method: 'POST', body })
// after
fetch('/api/v1/channels/'+id+'/messages', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}` }, body }) Defensive patterns
Strategy: validation
Validate before calling
const token = await getAccessToken();
if (!token) throw new Error('Login required before sending messages'); Try / catch
try { await sendMessage(cmd); }
catch (e) { if (e.status === 401) { await relogin(); retry(); } else throw e; } Prevention
- Attach Authorization headers via a central HTTP interceptor
- Refresh tokens proactively before expiry
- Never call authenticated endpoints from anonymous contexts
- Require auth on the endpoint (no AllowAnonymous)
When it happens
Trigger: POST to the send-message endpoint without a valid JWT, with an expired/anonymous token, or on an endpoint misconfigured to allow anonymous access so ICurrentUser resolves to Guid.Empty.
Common situations: Missing Authorization header in the client, expired access token, JWT authentication middleware not registered/ordered correctly, calling the endpoint from a background job or SignalR context without forwarding the user's token.
Related errors
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/f3fbfed2e4b2f9a7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Chat/Modules.Chat/Features/v1/Messages/SendMessage/SendMessageCommandHandler.cs:32
using Mediator;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace FSH.Modules.Chat.Features.v1.Messages.SendMessage;
public sealed class SendMessageCommandHandler(
ChatDbContext db,
ICurrentUser currentUser,
IHubContext<AppHub> hub,
IMentionResolver mentionResolver,
IEventBus eventBus)
: ICommandHandler<SendMessageCommand, MessageDto>
{
public async ValueTask<MessageDto> Handle(SendMessageCommand 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.");
channel.RequireMember(currentUserId);
Message? parent = null;
if (cmd.ParentMessageId is { } parentId)
{
parent = await db.Messages.FirstOrDefaultAsync(m => m.Id == parentId, cancellationToken)
.ConfigureAwait(false)
?? throw new NotFoundException("Parent message not found.");
if (parent.ChannelId != channel.Id)
{
throw new CustomException("Parent message belongs to a different channel.", (IEnumerable<string>?)null, HttpStatusCode.BadRequest);
}View on GitHub (pinned to 3f2959e683)