{"record":{"id":"f3fbfed2e4b2f9a7","repo":"fullstackhero/dotnet-starter-kit","slug":"no-current-user-sendmessagecommandhandler","errorCode":null,"errorMessage":"no current user","messagePattern":"no current user","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"src/Modules/Chat/Modules.Chat/Features/v1/Messages/SendMessage/SendMessageCommandHandler.cs","lineNumber":32,"sourceCode":"using Mediator;\nusing Microsoft.AspNetCore.SignalR;\nusing Microsoft.EntityFrameworkCore;\n\nnamespace FSH.Modules.Chat.Features.v1.Messages.SendMessage;\n\npublic sealed class SendMessageCommandHandler(\n    ChatDbContext db,\n    ICurrentUser currentUser,\n    IHubContext<AppHub> hub,\n    IMentionResolver mentionResolver,\n    IEventBus eventBus)\n    : ICommandHandler<SendMessageCommand, MessageDto>\n{\n    public async ValueTask<MessageDto> Handle(SendMessageCommand cmd, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(cmd);\n        var userId = currentUser.GetUserId();\n        if (userId == Guid.Empty) throw new UnauthorizedException(\"no current user\");\n        var currentUserId = userId.ToString();\n\n        var channel = await db.Channels.FirstOrDefaultAsync(c => c.Id == cmd.ChannelId, cancellationToken)\n            .ConfigureAwait(false)\n            ?? throw new NotFoundException(\"Channel not found.\");\n\n        channel.RequireMember(currentUserId);\n\n        Message? parent = null;\n        if (cmd.ParentMessageId is { } parentId)\n        {\n            parent = await db.Messages.FirstOrDefaultAsync(m => m.Id == parentId, cancellationToken)\n                .ConfigureAwait(false)\n                ?? throw new NotFoundException(\"Parent message not found.\");\n            if (parent.ChannelId != channel.Id)\n            {\n                throw new CustomException(\"Parent message belongs to a different channel.\", (IEnumerable<string>?)null, HttpStatusCode.BadRequest);\n            }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Chat/Modules.Chat/Features/v1/Messages/SendMessage/SendMessageCommandHandler.cs#L14-L50","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nfetch('/api/v1/channels/'+id+'/messages', { method: 'POST', body })\n// after\nfetch('/api/v1/channels/'+id+'/messages', { method: 'POST', headers: { Authorization: `Bearer ${accessToken}` }, body })","handlingStrategy":"validation","validationCode":"const token = await getAccessToken();\nif (!token) throw new Error('Login required before sending messages');","typeGuard":null,"tryCatchPattern":"try { await sendMessage(cmd); }\ncatch (e) { if (e.status === 401) { await relogin(); retry(); } else throw e; }","preventionTips":["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)"],"tags":["auth","chat","jwt"],"backgroundTag":"authentication-required","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}