fullstackhero/dotnet-starter-kit · error · CustomException
Cannot create a ticket without an authenticated reporter.
Error message
Cannot create a ticket without an authenticated reporter.
What it means
CreateTicketCommandHandler resolves the reporter via currentUser.GetUserId(); a Guid.Empty result (unauthenticated or anonymous principal) triggers a 401 CustomException because every ticket must record who reported it. The ticket number sequence (TK-n) also depends on a valid tenant/authenticated context.
Solutions
- Attach a valid Bearer token (or service-identity token) to the create-ticket request.
- Refresh expired credentials and retry.
- For machine callers, provision a dedicated service account and authenticate as it before creating tickets.
- In tests, stub ICurrentUser.GetUserId() to return a real user Guid.
Example fix
// before var handler = new CreateTicketCommandHandler(dbContext, currentUserSubstitute); // GetUserId() => Guid.Empty // after var currentUser = Substitute.For<ICurrentUser>(); currentUser.GetUserId().Returns(Guid.NewGuid()); var handler = new CreateTicketCommandHandler(dbContext, currentUser);
Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrWhiteSpace(token) || jwtSecurityToken == null)
throw new InvalidOperationException("A valid token is required to create a ticket."); Type guard
static bool CanCreateTicket(ICurrentUser user) => user.GetUserId() != Guid.Empty;
Try / catch
try { await mediator.Send(new CreateTicketCommand { ... }); }
catch (CustomException ex) when (ex.StatusCode == HttpStatusCode.Unauthorized) { await signInAgain(); } Prevention
- Gate the create-ticket route behind authentication so the token always exists.
- Provision service accounts for machine callers that create tickets.
- Refresh tokens proactively before long-running UI sessions submit forms.
- In handler tests, always stub GetUserId with a non-empty Guid.
When it happens
Trigger: Posting CreateTicketCommand without a valid JWT, with an expired token, or via an endpoint missing its authorization requirement so ICurrentUser has no user id.
Common situations: Scheduled jobs or webhooks calling the create endpoint with service credentials not configured; frontend losing the token after refresh; tests constructing the handler with a default/mock ICurrentUser returning Guid.Empty.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Cannot post a comment without an authenticated author.
- no current user
- no current user
- no current user
- no current user
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/6b1a5b5354d54393.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Tickets/Modules.Tickets/Features/v1/Tickets/CreateTicket/CreateTicketCommandHandler.cs:26
using Mediator;
using FSH.Framework.Persistence;
using Microsoft.EntityFrameworkCore;
namespace FSH.Modules.Tickets.Features.v1.Tickets.CreateTicket;
public sealed class CreateTicketCommandHandler(
TicketsDbContext dbContext,
ICurrentUser currentUser)
: ICommandHandler<CreateTicketCommand, Guid>
{
public async ValueTask<Guid> Handle(CreateTicketCommand command, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(command);
var reporterId = currentUser.GetUserId();
if (reporterId == Guid.Empty)
{
throw new CustomException(
"Cannot create a ticket without an authenticated reporter.",
(IEnumerable<string>?)null,
HttpStatusCode.Unauthorized);
}
// Sequential, tenant-scoped ticket numbers (TK-1, …). Count ALL rows incl. soft-deleted so a
// deleted number isn't reused; racing writers collide on the unique index (→ 409, retryable).
long count = await dbContext.Tickets
.IgnoreQueryFilters([QueryFilters.SoftDelete])
.LongCountAsync(cancellationToken)
.ConfigureAwait(false);
string number = $"TK-{(count + 1).ToString(CultureInfo.InvariantCulture)}";
var ticket = Ticket.Create(
number: number,
title: command.Title,
description: command.Description,
priority: command.Priority,View on GitHub (pinned to 3f2959e683)