The hosts scored two quick goals either side of half-time through Gatetan Laborde and Flavien Tait.
Mauricio Pochettino’s side did not have a single shot on target, despite Messi, Neymar and Kylian Mbappe all starting.
The defeat is PSG’s first in Ligue 1 since April, when they were beaten by last season’s eventual champions Lille.
Rennes opened the scoring on 44 minutes when Laborde converted from Kamaldeen Sulemana’s superb cross.
Tait added a second soon after the restart with a sweeping finish into the bottom corner.
After slicing an effort high over the bar in the first half, Mbappe thought he had pulled a goal back for Pochettino’s side midway through the second half, only for it to be ruled out for offside by the video assistant referee (VAR).
The Frenchman is now on a run of five games without a goal in all competitions.
PSG were spared further damage when referee Ruddy Buquet reversed his decision to award Rennes a penalty for Achraf Hakimi’s foul on Laborde after checking the pitchside monitor.
Neymar missed a volley in the first half and Idrissa Gueye fired wide of the post, but Lionel Messi came closest for PSG when he hit the crossbar from a free-kick.
Bruno Genesio’s Rennes side had only won twice in Ligue 1 heading into Sunday’s game, but were clinical in front of goal and scored from two of their four shots on target.
The result leaves PSG top of Ligue 1 on 24 points, six points clear of Lens, while Rennes move up to seventh.