fullstackhero/dotnet-starter-kit · error · CustomException

A closed ticket cannot be edited — reopen it first.

Error message

A closed ticket cannot be edited — reopen it first.

What it means

Ticket.UpdateDetails refuses to edit a Closed ticket, throwing CustomException with HTTP 409 Conflict. Closed tickets are immutable in this domain; they must be reopened before title, description, or priority can change. The title argument is also validated as non-empty before this check.

Solutions

  1. Reopen the ticket first, then apply the update.
  2. Reload the ticket to refresh Status before editing.
  3. Handle 409 in the client and offer a 'Reopen and edit' action.
  4. Disable edit controls in the UI when the ticket status is Closed.

Example fix

// before
ticket.UpdateDetails(title, description, priority); // 409 if closed
// after
if (ticket.Status == TicketStatus.Closed)
{
    ticket.Reopen();
}
ticket.UpdateDetails(title, description, priority);
Defensive patterns

Strategy: validation

Validate before calling

if (ticket.status === TicketStatus.Closed) {
  throw new Error('Reopen the ticket before editing.');
}
if (!title?.trim()) {
  throw new Error('Title is required.');
}
ticket.updateDetails(title, description, priority);

Type guard

bool CanEdit(Ticket t) => t.Status != TicketStatus.Closed && !string.IsNullOrWhiteSpace(t.Title);

Try / catch

try
{
    ticket.UpdateDetails(title, description, priority);
}
catch (CustomException ex) when (ex.StatusCode == HttpStatusCode.Conflict)
{
    ticket.Reopen();
    ticket.UpdateDetails(title, description, priority);
}

Prevention

When it happens

Trigger: Calling UpdateDetails (or the update-ticket endpoint) on a ticket with Status == TicketStatus.Closed.

Common situations: Editing an old ticket from a stale browser tab after someone closed it; concurrent edits where close won the race; automated bulk-update jobs not checking status.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Modules/Tickets/Modules.Tickets/Domain/Ticket.cs:168

                (IEnumerable<string>?)null,
                HttpStatusCode.Conflict);
        }

        ClosedAtUtc = DateTime.UtcNow;
        UpdatedAtUtc = DateTime.UtcNow;
        TransitionStatus(TicketStatus.Closed);
    }

    /// <summary>
    /// Edits the mutable details of an open/in-progress/resolved ticket. A closed ticket is
    /// frozen — it must be reopened first.
    /// </summary>
    public void UpdateDetails(string title, string? description, TicketPriority priority)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(title);
        if (Status == TicketStatus.Closed)
        {
            throw new CustomException(
                "A closed ticket cannot be edited — reopen it first.",
                (IEnumerable<string>?)null,
                HttpStatusCode.Conflict);
        }

        Title = title.Trim();
        Description = string.IsNullOrWhiteSpace(description) ? null : description.Trim();
        Priority = priority;
        UpdatedAtUtc = DateTime.UtcNow;
    }

    public void Reopen()
    {
        if (Status is TicketStatus.Open or TicketStatus.InProgress)
        {
            return;
        }

View on GitHub (pinned to 3f2959e683)