diff --git a/apps/api/src/collectives/matrix-provisioner.ts b/apps/api/src/collectives/matrix-provisioner.ts index 7b216b4..3947ade 100644 --- a/apps/api/src/collectives/matrix-provisioner.ts +++ b/apps/api/src/collectives/matrix-provisioner.ts @@ -186,7 +186,23 @@ export class MatrixProvisioner implements ProvisionerPort { power_level_content_override: this.powerLevels(input), }); for (const [index, text] of onboardingSequence(input.language).entries()) { - await this.post(roomId, index, { msgtype: "m.text", body: text }); + // A brand-new room can reject the first posts until its initial events + // settle ("no forward extremities"); retry rather than fail the whole + // collective for a race measured in milliseconds. + let lastError: unknown = null; + for (const delayMs of [0, 1000, 2500, 5000]) { + if (delayMs > 0) await new Promise((r) => setTimeout(r, delayMs)); + try { + await this.post(roomId, index, { msgtype: "m.text", body: text }); + lastError = null; + break; + } catch (err) { + lastError = err; + } + } + if (lastError !== null) { + this.logger.warn(`onboarding guide post ${index} failed after retries in ${roomId}: ${errorText(lastError)}`); + } } if (input.founderMxid !== null) await this.inviteUser(roomId, input.founderMxid); return { roomId };