Skip to content

🐛 [BUG] - Décompte des membres des rôles admin en échec 500 (NaN) quand des rôles OIDC sont portés #2781

Description

@shikanime

Description

L'ouverture de la page Administration > Rôles affiche une notification d'erreur et le décompte des membres ne s'affiche plus pour aucun rôle. L'endpoint GET /api/v1/admin/roles/member-counts renvoie une 500 : le corps produit par le handler actuellement servi (fallback legacy apps/server) échoue sa propre validation de contrat ts-rest côté serveur.

Déclencheur : au moins un utilisateur porteur d'un rôle admin adossé à un groupe OIDC (oidcGroup non vide). Le décompte est calculé en mémoire à partir des adminRoleIds des utilisateurs ; un id OIDC absent de l'index pré-initialisé passe par undefined++ et produit NaN, que le contrat z.record(z.number()) rejette pour la réponse entière.

Impact : perte du décompte des membres sur toute la page Rôles pour tous les administrateurs, tant que la route reste servie par le legacy — lequel est gelé pour les contributions (cf. CONTRIBUTING.md).

Etapes de reproduction

  1. Se placer sur une instance où /api/v1/admin/roles est servie par apps/server (défaut actuel du routage nginx-strangler)
  2. Garantir qu'au moins un utilisateur porte un rôle admin avec oidcGroup non vide
  3. Ouvrir Administration > Rôles
  4. Observer la notification [ts-rest] Response validation failed for GET /api/v1/admin/roles/member-counts: … et l'absence des décomptes

Captures d'écran

Logs

[ts-rest] Response validation failed for GET /api/v1/admin/roles/member-counts: [
  {
    "code": "invalid_type",
    "expected": "number",
    "received": "nan",
    "path": [
      "6bebe7b2-0f0a-456e-ab7f-b3d7640a7cbf"
    ],
    "message": "Expected number, received nan"
  },
  {
    "code": "invalid_type",
    "expected": "number",
    "received": "nan",
    "path": [
      "76229c96-4716-45bc-99da-00498ec9018c"
    ],
    "message": "Expected number, received nan"
  }
]

Navigateurs

OS

Version de la console impactée

Définition du fini

Références

Activity

  1. added this to the 9.27.0 milestone on Sep 28, 2026
  2. self-assigned this
    on Sep 28, 2026
  3. shikanime commented on Sep 28, 2026

    @shikanime
    MemberAuthor

    Cause racine (analyse)

    La route est encore servie par le legacy : aucune location /api/v1/admin/roles n'existe dans apps/nginx-strangler/conf.d/routing.conf, le fallback location /api/ route vers apps/server (gelé).

    countRolesMembers() (apps/server/src/resources/admin-role/business.ts:72-83) n'indexe que les rôles oidcGroup = '' (ligne 73), puis incrémente rolesCounts[roleId]++ (ligne 82) pour tous les ids portés par les utilisateurs. Pour un id de rôle OIDC — absent de l'index — undefined++ produit NaN.

    La réponse est validée côté serveur (responseValidation: true, apps/server/src/resources/index.ts:26) contre z.record(z.number().min(0)) (packages/shared/src/contracts/admin-role.ts:50) : une seule valeur NaN invalide la réponse entière, transformée en 500 par setErrorHandler (apps/server/src/app.ts:39-45).

    Reproduit localement avec le vrai plugin @ts-rest/fastify (responseValidation: true, données portant deux ids OIDC) : HTTP 500, message [ts-rest] Response validation failed for GET /api/v1/admin/roles/member-counts: … identique à celui de la capture.

    Contre-vérifications : l'implémentation server-nestjs (apps/server-nestjs/src/modules/admin-role/admin-role-queries.utils.ts:58) ignore déjà les ids OIDC (if (typeof counts[roleId] === 'number')) ; le défaut ne vient donc pas du portage, mais du serveur legacy que la route continue d'utiliser. Le client n'est pas en cause non plus (validation de réponse désactivée côté client ; la 500 est émise par le serveur).

    Chemin de correction

    apps/server étant gelé (CONTRIBUTING.md : « ne reçoit plus de contribution, y compris pour une correction de bug »), le correctif passe par la bascule de /api/v1/admin/roles vers server-nestjs :

  4. shikanime commented on Sep 28, 2026

    @shikanime
    MemberAuthor

    Correctif

    PR #2782 — feat(nginx-strangler): route /api/v1/admin/roles to server-nestjs — est prête à la revue (CI verte, 32/32 checks) :

    • bascule de /api/v1/admin/roles vers server-nestjs (décompte sans NaN) ;
    • specs verrouillant l'exclusion des ids OIDC et la conformité de la réponse au contrat.

    À fusionner après #2749 (prérequis, cf. #2723).

  5. shikanime commented on Sep 28, 2026

    @shikanime
    MemberAuthor

    Correctifs

    Le socle de la pile (21/08) précède le module admin-role, d'où cette séparation.

  6. added theissue type on Sep 29, 2026
  7. 7 remaining items

  8. modified the milestones: 9.28.0, 9.29.0 on Oct 5, 2026
  9. modified the milestones: 9.29.0, 9.27.0 on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions