{"record":{"id":"78b8742cfbc3ee0b","repo":"plandex-ai/plandex","slug":"error-deleting-invite-v","errorCode":null,"errorMessage":"error deleting invite: %v","messagePattern":"error deleting invite: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/invite_helpers.go","lineNumber":111,"sourceCode":"\n\t\treturn nil, fmt.Errorf(\"error getting invites and org names for email: %v\", err)\n\t}\n\n\treturn invites, nil\n}\n\nfunc DeleteInvite(id string, tx *sqlx.Tx) error {\n\tquery := \"DELETE FROM invites WHERE id = $1\"\n\tvar err error\n\n\tif tx == nil {\n\t\t_, err = Conn.Exec(query, id)\n\t} else {\n\t\t_, err = tx.Exec(query, id)\n\t}\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting invite: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc AcceptInvite(ctx context.Context, invite *Invite, inviteeId string) error {\n\terr := WithTx(ctx, \"accept invite\", func(tx *sqlx.Tx) error {\n\n\t\t_, err := tx.Exec(`UPDATE invites SET accepted_at = NOW(), invitee_id = $1 WHERE id = $2`, inviteeId, invite.Id)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error accepting invite: %v\", err)\n\t\t}\n\n\t\t// create org user\n\t\terr = CreateOrgUser(invite.OrgId, inviteeId, invite.OrgRoleId, tx)\n\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error creating org user: %v\", err)","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/invite_helpers.go#L93-L129","documentation":"DeleteInvite removes an invite row either on the standalone connection (Conn.Exec) or inside a supplied transaction (tx.Exec), depending on whether a tx is passed. Any Exec failure is wrapped with this message. It indicates the DELETE statement failed at the database level, not that the invite didn't exist.","triggerScenarios":"DELETE FROM invites WHERE id = $1 fails: malformed id vs. uuid column (invalid input syntax for type uuid), connection failure/timeout, transaction already aborted by an earlier statement, or FK restriction if other tables reference invites.","commonSituations":"DeleteInviteHandler given a tampered/malformed invite id; deleting inside a WithTx block after CreateOrgUser or another statement already failed and poisoned the transaction; FK constraints added by newer migrations blocking deletion.","solutions":["Validate the invite id format (UUID parse) in the handler before calling DeleteInvite.","Unwrap with errors.As(*pq.Error/*pgconn.PgError): 22P02 means bad id format; 23503 means FK restriction.","If using the tx path, ensure no earlier statement in the transaction failed — check and rollback before this call.","Check for dependent rows in referencing tables if FK errors appear.","Verify DB connectivity if the cause is a connection error."],"exampleFix":"// before: transaction reused after failure\nif err := CreateOrgUser(...); err != nil {\n    // tx is now aborted, later DeleteInvite fails mysteriously\n}\nerr := db.DeleteInvite(id, tx)\n\n// after: handle failure and rollback before proceeding\nif err := CreateOrgUser(...); err != nil {\n    return fmt.Errorf(\"create org user: %w\", err) // tx rolled back by WithTx\n}\nif _, err := uuid.Parse(id); err != nil {\n    return fmt.Errorf(\"invalid invite id %q\", id)\n}\nerr := db.DeleteInvite(id, tx)","handlingStrategy":"validation","validationCode":"if _, err := uuid.Parse(inviteId); err != nil {\n    return fmt.Errorf(\"invalid invite id %q\", inviteId)\n}","typeGuard":"func isInvalidTextRep(err error) bool {\n    var pgErr *pq.Error\n    return errors.As(err, &pgErr) && pgErr.Code == \"22P02\"\n}","tryCatchPattern":"if err := db.DeleteInvite(id, tx); err != nil {\n    if isInvalidTextRep(err) {\n        return fmt.Errorf(\"bad invite id: %w\", err)\n    }\n    var pgErr *pq.Error\n    if errors.As(err, &pgErr) && pgErr.Code == \"23503\" {\n        return fmt.Errorf(\"invite referenced by other rows: %w\", err)\n    }\n    return fmt.Errorf(\"delete invite: %w\", err)\n}","preventionTips":["Validate id format at the HTTP boundary before any DB call.","Never continue using a tx after a failed statement — abort/rollback immediately.","Check foreign keys referencing invites before enabling deletes.","Keep driver error codes inspectable by wrapping with %w.","Log invite id (sanitized) with the failure for traceability."],"tags":["database","sql","delete","transaction","foreign-key"],"backgroundTag":"database-delete-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}