@@ -127,7 +127,11 @@ func (s AGPLIDPSync) SyncOrganizations(ctx context.Context, tx database.Store, u
127
127
// Find the difference in the expected and the existing orgs, and
128
128
// correct the set of orgs the user is a member of.
129
129
add ,remove := slice .SymmetricDifference (existingOrgIDs ,finalExpected )
130
- notExists := make ([]uuid.UUID ,0 )
130
+ // notExists is purely for debugging. It logs when the settings want
131
+ // a user in an organization, but the organization does not exist.
132
+ notExists := slice .DifferenceFunc (expectedOrgIDs ,finalExpected ,func (a ,b uuid.UUID )bool {
133
+ return a == b
134
+ })
131
135
for _ ,orgID := range add {
132
136
_ ,err := tx .InsertOrganizationMember (ctx , database.InsertOrganizationMemberParams {
133
137
OrganizationID :orgID ,
@@ -138,9 +142,26 @@ func (s AGPLIDPSync) SyncOrganizations(ctx context.Context, tx database.Store, u
138
142
})
139
143
if err != nil {
140
144
if xerrors .Is (err ,sql .ErrNoRows ) {
145
+ // This should not happen because we check the org existance
146
+ // beforehand.
141
147
notExists = append (notExists ,orgID )
142
148
continue
143
149
}
150
+
151
+ if database .IsUniqueViolation (err ,database .UniqueOrganizationMembersPkey ) {
152
+ // If we hit this error we have a bug. The user already exists in the
153
+ // organization, but was not detected to be at the start of this function.
154
+ // Instead of failing the function, an error will be logged. This is to not bring
155
+ // down the entire syncing behavior from a single failed org. Failing this can
156
+ // prevent user logins, so only fatal non-recoverable errors should be returned.
157
+ s .Logger .Error (ctx ,"syncing user to organization failed as they are already a member, please report this failure to Coder" ,
158
+ slog .F ("user_id" ,user .ID ),
159
+ slog .F ("username" ,user .Username ),
160
+ slog .F ("organization_id" ,orgID ),
161
+ slog .Error (err ),
162
+ )
163
+ continue
164
+ }
144
165
return xerrors .Errorf ("add user to organization: %w" ,err )
145
166
}
146
167
}
@@ -156,6 +177,7 @@ func (s AGPLIDPSync) SyncOrganizations(ctx context.Context, tx database.Store, u
156
177
}
157
178
158
179
if len (notExists )> 0 {
180
+ notExists = slice .Unique (notExists )// Remove dupes
159
181
s .Logger .Debug (ctx ,"organizations do not exist but attempted to use in org sync" ,
160
182
slog .F ("not_found" ,notExists ),
161
183
slog .F ("user_id" ,user .ID ),