{"record":{"id":"c84f5a08cac63037","repo":"fullstackhero/dotnet-starter-kit","slug":"audit-record-query-id-not-found","errorCode":null,"errorMessage":"Audit record {query.Id} not found.","messagePattern":"Audit record (.+?) not found\\.","errorType":"exception","errorClass":"KeyNotFoundException","httpStatus":404,"severity":"warning","filePath":"src/Modules/Auditing/Modules.Auditing/Features/v1/GetAuditById/GetAuditByIdQueryHandler.cs","lineNumber":36,"sourceCode":"    {\n        _dbContext = dbContext;\n        _logger = logger;\n    }\n\n    public async ValueTask<AuditDetailDto> Handle(GetAuditByIdQuery query, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(query);\n\n        var record = await _dbContext.AuditRecords\n            .AsNoTracking()\n            .FirstOrDefaultAsync(a => a.Id == query.Id, cancellationToken)\n            .ConfigureAwait(false);\n\n        if (record is null)\n        {\n            // KeyNotFoundException maps to 404 globally. Kept (not framework NotFoundException)\n            // because audit exception-type fixtures and severity classification key off this type.\n            throw new KeyNotFoundException($\"Audit record {query.Id} not found.\");\n        }\n\n        JsonElement payload;\n        try\n        {\n            using var document = JsonDocument.Parse(record.PayloadJson);\n            payload = document.RootElement.Clone();\n        }\n        catch (JsonException ex)\n        {\n            _logger.LogWarning(ex, \"Failed to parse audit payload JSON for record {AuditId}.\", query.Id);\n            payload = JsonDocument.Parse(\"{}\").RootElement.Clone();\n        }\n\n        return new AuditDetailDto\n        {\n            Id = record.Id,\n            OccurredAtUtc = record.OccurredAtUtc,","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Auditing/Modules.Auditing/Features/v1/GetAuditById/GetAuditByIdQueryHandler.cs#L18-L54","documentation":"GetAuditByIdQueryHandler throws KeyNotFoundException when no AuditRecord with the requested Id exists in the database. The handler intentionally uses KeyNotFoundException (rather than the framework's NotFoundException) because audit exception-type fixtures and severity classification key off this type; it maps to HTTP 404 globally.","triggerScenarios":"Calling the GET audit-by-id endpoint with an Id that does not exist, an Id belonging to another tenant (filtered out by the tenant query filter), or an already-deleted audit record.","commonSituations":"Stale client-side links after audit retention purges records; querying an audit id copied from a different tenant's environment; typos or case issues when constructing the id manually.","solutions":["Verify the audit record Id exists and belongs to the current tenant (query the AuditRecords table).","Check the X-Tenant header / tenant resolution so the query filter does not exclude the record.","Handle 404 on the client and show a not-found state instead of treating it as a bug.","If tests reference the id, re-seed audit data since fixtures are not persistent."],"exampleFix":"// before\nvar audit = await client.GetAuditAsync(\"0e2f...\"); // throws\n\n// after\ntry\n{\n    var audit = await client.GetAuditAsync(id);\n}\ncatch (HttpRequestException) when (http.Response.StatusCode == HttpStatusCode.NotFound)\n{\n    // record missing or in another tenant\n}","handlingStrategy":"try-catch","validationCode":"var exists = await dbContext.AuditRecords.AnyAsync(a => a.Id == id); if (!exists) return NotFound();","typeGuard":null,"tryCatchPattern":"try { var audit = await api.GetAuditById(id); } catch (Exception ex) when (ex is KeyNotFoundException || IsHttp404(ex)) { // show not-found UI }","preventionTips":["Confirm the record exists in the current tenant before deep-linking to it","Refresh audit id references after retention cleanup jobs","Treat 404 as a normal outcome in audit UIs, not an error banner"],"tags":["not-found","auditing","http-404"],"backgroundTag":"resource-not-found","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"}