{"record":{"id":"0d1844bc08f55718","repo":"Tencent/WeKnora","slug":"repository-pending-invitation-already-exists","errorCode":null,"errorMessage":"repository: pending invitation already exists","messagePattern":"repository: pending invitation already exists","errorType":"error_code","errorClass":null,"httpStatus":409,"severity":"error","filePath":"internal/application/repository/tenant_invitation.go","lineNumber":16,"sourceCode":"package repository\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/Tencent/WeKnora/internal/types\"\n\t\"github.com/Tencent/WeKnora/internal/types/interfaces\"\n\t\"gorm.io/gorm\"\n)\n\n// ErrPendingInvitationExists is returned by Create when a pending\n// invitation for (tenant_id, invitee_user_id) already exists. The\n// service layer maps it to its own sentinel for the handler.\nvar ErrPendingInvitationExists = errors.New(\"repository: pending invitation already exists\")\n\n// tenantInvitationRepository implements interfaces.TenantInvitationRepository.\ntype tenantInvitationRepository struct {\n\tdb *gorm.DB\n}\n\n// NewTenantInvitationRepository constructs the repo against db. Wired\n// up via the dig container alongside other repositories.\nfunc NewTenantInvitationRepository(db *gorm.DB) interfaces.TenantInvitationRepository {\n\treturn &tenantInvitationRepository{db: db}\n}\n\n// Create inserts a new pending invitation row. The partial unique\n// index on (tenant_id, invitee_user_id) WHERE status='pending' is the\n// authoritative guard against duplicates, but we ALSO pre-check via\n// GetPendingByPair inside a tiny transaction so the typical \"click\n// twice fast\" case returns a clean sentinel instead of a raw 23505 /\n// SQLITE_CONSTRAINT error string the handler would have to parse.","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/repository/tenant_invitation.go#L1-L34","documentation":"Sentinel ErrPendingInvitationExists returned by invitation repository Create when inserting hits a unique-conflict on (tenant_id, invitee_user_id) because an already-pending invitation exists. The service layer re-maps it to its own sentinel and the handler responds 409 Conflict.","triggerScenarios":"Thrown at internal/application/repository/tenant_invitation.go:16 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Do not create a duplicate; notify the user that an invitation is already pending","If the old invitation should be replaced, revoke/cancel it first, then create the new one"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}