Non-Error promise rejection captured with value: undefined. Voilà ce que Sentry affiche le plus souvent quand une requête vers l’API REST de WordPress échoue depuis un composant monté côté client d’un front Next.js. L’erreur existe bel et bien, mais elle est aveugle : impossible de savoir quelle route a été appelée, avec quels paramètres, ni ce que WordPress a renvoyé de son côté au même instant.
Ce sont deux applications distinctes, deux runtimes, et surtout deux instances Sentry séparées si l’on installe le SDK des deux côtés sans réfléchir à leur articulation. Le correctif ne demande ni service tiers ni infrastructure supplémentaire : un identifiant de corrélation, généré côté front, transmis en en-tête à chaque appel, et rejoué comme tag dans les deux événements Sentry.
Le problème : deux journaux qui ne se parlent jamais
Par défaut, le SDK @sentry/nextjs capture les rejets de promesses et les exceptions non gérées côté client, avec le contexte du navigateur (user agent, URL, breadcrumbs de navigation). Le SDK @sentry/node côté WordPress — via un plugin qui encapsule les appels à l’API Sentry — capture, lui, le contexte serveur : requête PHP, hooks actifs, éventuellement la requête SQL en cause. Chacun raconte une moitié de l’histoire.
Sur un projet avec plusieurs dizaines de milliers de visites mensuelles, ce découplage devient un vrai coût : chaque incident oblige à croiser manuellement les horodatages des deux dashboards Sentry, en espérant que les horloges des deux serveurs soient bien synchronisées à la seconde près. Ce n’est pas toujours le cas.
Choisir et propager un identifiant de corrélation
La solution la plus simple reste un UUID v4 généré au tout début de chaque requête entrante côté Next.js, dans le middleware ou dans getServerSideProps selon le type de rendu. Cet identifiant voyage ensuite dans un en-tête HTTP dédié vers l’API REST de WordPress, puis revient tel quel dans la réponse.

- Générer l’identifiant côté Next.js avec
crypto.randomUUID()(ou le moduleuuidpour les versions de Node antérieures) au démarrage de chaque requête. - L’attacher à toutes les requêtes sortantes vers WordPress dans un en-tête personnalisé, par exemple
X-Correlation-Id. - Côté WordPress, lire cet en-tête via
$_SERVER['HTTP_X_CORRELATION_ID']dans le point d’entrée REST et le renvoyer dans la réponse viarest_ensure_response. - Configurer
Sentry.setTag('correlation_id', id)avant tout appel réseau, des deux côtés. - Filtrer par ce tag dans l’interface Sentry pour retrouver la paire d’événements front/back en une recherche.
Envoyer l’identifiant depuis Next.js
Voici un wrapper minimal autour de fetch qui centralise la génération et l’envoi de l’identifiant :
import * as Sentry from '@sentry/nextjs';
import { randomUUID } from 'crypto';
export async function fetchFromWordPress(path, options = {}) {
const correlationId = randomUUID();
Sentry.setTag('correlation_id', correlationId);
const response = await fetch(`${process.env.WP_API_URL}${path}`, {
...options,
headers: {
...options.headers,
'X-Correlation-Id': correlationId,
},
});
if (!response.ok) {
Sentry.captureMessage(`Echec appel WordPress: ${path}`, {
level: 'error',
tags: { correlation_id: correlationId, status: response.status },
});
}
return response;
}
Chaque appel passe désormais par ce point unique, garantissant que l’identifiant n’est jamais oublié sur une route ajoutée à la va-vite.
Recevoir et logguer l’identifiant côté WordPress
Côté serveur, un filtre générique appliqué à toutes les routes REST permet d’attacher le tag sans dupliquer du code dans chaque contrôleur :
add_filter('rest_pre_dispatch', function ($result, $server, $request) {
$correlation_id = $request->get_header('x-correlation-id');
if ($correlation_id && function_exists('Sentry\configureScope')) {
\Sentry\configureScope(function ($scope) use ($correlation_id) {
$scope->setTag('correlation_id', $correlation_id);
});
}
return $result;
}, 10, 3);
Le hook rest_pre_dispatch s’exécute avant chaque callback de route, ce qui en fait un point d’accroche fiable pour ce genre de traitement transverse.
Retrouver la paire dans Sentry
Une fois les deux tags en place, la recherche dans l’interface Sentry devient triviale : correlation_id:8f3e... fait remonter les deux événements, front et back, côte à côte. Le temps de diagnostic d’un incident chute nettement, puisqu’il n’est plus nécessaire de recouper des horodatages approximatifs entre deux fuseaux horaires de serveurs différents.
- L’identifiant ne remplace pas un vrai système de traçage distribué, mais il coûte une ligne de code par appel.
- Il fonctionne aussi bien en SSR qu’en génération statique avec revalidation, tant que l’appel réseau passe par le même wrapper.
- Il n’a aucune incidence sur la configuration des alertes ou des seuils Sentry, qui reste un sujet à part entière.
Un identifiant de corrélation n’a de valeur que s’il est propagé partout, tout le temps. Le jour où un développeur pressé appelle
fetchdirectement sans passer par le wrapper, la chaîne casse silencieusement.
En résumé
Deux SDK Sentry, un par application, restent la bonne architecture pour un projet headless. Ce qui manquait, c’était le fil qui les relie : un identifiant généré une fois, transmis en en-tête, et posé comme tag des deux côtés. Rien de plus, mais rien de moins non plus — sans lui, chaque incident reste une enquête à deux fuseaux horaires.