fullstackhero/dotnet-starter-kit · error · UnauthorizedException

no current user

Error message

no current user

What it means

DiscoverChannelsQueryHandler throws UnauthorizedException when currentUser.GetUserId() returns Guid.Empty — discovery is scoped to the calling user (it excludes their existing memberships), so an anonymous request cannot be served.

Solutions

  1. Attach a valid bearer token to the discovery request
  2. Implement 401 handling: refresh token and retry once
  3. In tests, mock ICurrentUser.GetUserId() to return a real Guid

Example fix

// before
const res = await fetch('/api/v1/channels/discover'); // 401 no current user
// after
const res = await apiFetch('/api/v1/channels/discover'); // apiFetch attaches JWT and handles 401 refresh
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 discover(); }
catch (UnauthorizedException) { /* refresh token and retry once */ }

Prevention

When it happens

Trigger: GET channel discovery without a valid JWT, expired token, or calling the query handler directly in tests with an unauthenticated ICurrentUser.

Common situations: Token expired while browsing; missing Authorization header on a 'public-looking' endpoint the developer assumed was anonymous; tests forgetting auth setup.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/446229cf1618e9a7. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Chat/Modules.Chat/Features/v1/Channels/DiscoverChannels/DiscoverChannelsQueryHandler.cs:23

using FSH.Modules.Chat.Contracts.v1.Queries;
using FSH.Modules.Chat.Data;
using FSH.Modules.Chat.Domain;
using FSH.Modules.Chat.Features.v1.Internal;
using Mediator;
using Microsoft.EntityFrameworkCore;

namespace FSH.Modules.Chat.Features.v1.Channels.DiscoverChannels;

public sealed class DiscoverChannelsQueryHandler(
    ChatDbContext db,
    ICurrentUser currentUser)
    : IQueryHandler<DiscoverChannelsQuery, ReadOnlyCollection<ChannelDto>>
{
    public async ValueTask<ReadOnlyCollection<ChannelDto>> Handle(DiscoverChannelsQuery q, CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(q);
        var userId = currentUser.GetUserId();
        if (userId == Guid.Empty) throw new UnauthorizedException("no current user");
        var currentUserId = userId.ToString();

        int page = Math.Max(1, q.Page);
        int pageSize = Math.Clamp(q.PageSize, 1, 200);

        var query = db.Channels.AsNoTracking()
            .Where(c => c.Type == ChannelType.Channel
                     && !c.IsPrivate
                     && !c.Members.Any(m => m.UserId == currentUserId));

        if (!string.IsNullOrWhiteSpace(q.Search))
        {
            var term = q.Search.Trim();
            query = query.Where(c =>
                EF.Functions.ILike(c.Name!, $"%{term}%")
                || EF.Functions.ILike(c.Slug!, $"%{term}%"));
        }

View on GitHub (pinned to 3f2959e683)