{"record":{"id":"8dd1c6bc8cbbd6a2","repo":"dotnet/eShop","slug":"request-with-id-already-exists","errorCode":null,"errorMessage":"Request with {id} already exists","messagePattern":"Request with (.+?) already exists","errorType":"exception","errorClass":"OrderingDomainException","httpStatus":null,"severity":"warning","filePath":"src/Ordering.Infrastructure/Idempotency/RequestManager.cs","lineNumber":26,"sourceCode":"    {\n        _context = context ?? throw new ArgumentNullException(nameof(context));\n    }\n\n\n    public async Task<bool> ExistAsync(Guid id)\n    {\n        var request = await _context.\n            FindAsync<ClientRequest>(id);\n\n        return request != null;\n    }\n\n    public async Task CreateRequestForCommandAsync<T>(Guid id)\n    {\n        var exists = await ExistAsync(id);\n\n        var request = exists ?\n            throw new OrderingDomainException($\"Request with {id} already exists\") :\n            new ClientRequest()\n            {\n                Id = id,\n                Name = typeof(T).Name,\n                Time = DateTime.UtcNow\n            };\n\n        _context.Add(request);\n\n        await _context.SaveChangesAsync();\n    }\n}\n","sourceCodeStart":8,"sourceCodeEnd":39,"githubUrl":"https://github.com/dotnet/eShop/blob/9b4f9434f46fdc5c1a6e9e936af2868340cdbc48/src/Ordering.Infrastructure/Idempotency/RequestManager.cs#L8-L39","documentation":"Thrown by RequestManager.CreateRequestForCommandAsync when a ClientRequest row with the given Guid id already exists. RequestManager implements the idempotency pattern: each command carries a unique request id, and the first time it is processed a ClientRequest is recorded. A second attempt with the same id is treated as a duplicate and rejected with an OrderingDomainException before the handler runs.","triggerScenarios":"The same command (same request id) is dispatched more than once — e.g. a client retry, a message-broker redelivery, or a saga re-sending. CreateRequestForCommandAsync is called by a CreateOrderCommandHandler behavior that checks ExistAsync first; on a hit it throws, preventing duplicate order creation.","commonSituations":"gRPC/HTTP client retrying on timeout after the server already processed the command; message queue redelivering the integration event; integration tests reusing a fixed request id across runs without clearing the Request table; a network blip causing the client to resend.","solutions":["Treat this exception as expected for duplicate delivery: catch OrderingDomainException from CreateRequestForCommandAsync and return the previously-completed result (or ack) instead of erroring — the work was already done.","Generate a fresh request id per logical command attempt on the client, and only reuse the id when deliberately retrying the SAME command for idempotency.","Ensure integration tests truncate/clear the ClientRequests table or use unique ids per run.","Verify the queue/dead-letter config is not redelivering long-after the command succeeded."],"exampleFix":"// before\nawait _requestManager.CreateRequestForCommandAsync<CreateOrderCommand>(id);\nawait _mediator.Send(command);\n\n// after\ntry {\n    await _requestManager.CreateRequestForCommandAsync<CreateOrderCommand>(id);\n} catch (OrderingDomainException) {\n    return; // duplicate delivery — command already processed, idempotent ack\n}\nawait _mediator.Send(command);","handlingStrategy":"try-catch","validationCode":"if (await requestManager.ExistAsync(id)) {\n    // duplicate delivery — skip processing, return prior result\n    return;\n}","typeGuard":"static bool IsDuplicateRequest(bool exists) => exists;","tryCatchPattern":"try {\n    await requestManager.CreateRequestForCommandAsync<CreateOrderCommand>(id);\n} catch (OrderingDomainException) {\n    // command already handled on a previous delivery — ack/idempotent return\n    return;\n}","preventionTips":["Treat the duplicate-request exception as expected, not as an error.","Generate fresh request ids per logical attempt; reuse only for explicit retries.","Clear the ClientRequests table (or use unique ids) in integration tests.","Acknowledge/redeliver-safe: design handlers to be idempotent beyond the RequestManager check."],"tags":["infrastructure","ordering","idempotency","duplicate","messaging"],"backgroundTag":null,"analyzedSha":"9b4f9434f46fdc5c1a6e9e936af2868340cdbc48","analyzedAt":"2026-08-13T19:29:36.594Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}