James Tedesco was also unlucky to avoid the sin bin, after a first-half professional foul.
That aside, the Roosters were the better team, suffocating the Warriors with their second-half defence and gradually wearing them down through the middle.
The Warriors were punished for a flat start after halftime – "leaving our words in the sheds" was how Shaun Johnson described it, and struggled to again get a foothold in the match.
But they battled manfully, often under immense pressure, and their yardage work, edge defence and goal-line scrambling was impressive.
It's the kind of performance to build on, as some key players return in the coming weeks.
Most of the pack had strong games, while both centres did well to shut down the Roosters threats out wide.
The home side made the better start on a hot afternoon, with the Warriors marooned in their own territory.
But after all their stout defence, the 15th minute try to Ed Kosi was a perfect fillip, after a deep pass from Chanel Harris-Tavita gave Adam Pompey the chance to put Kosi away.
The Warriors looked good but couldn't extend their advantage, before Daniel Tupou finished off a set move off, after two seven-tackle sets.
The Warriors could have created more pressure, but too often released the valve. There was a knock on early in the set after Kosi's try, then over-enthusiastic play led to another premature error deep in Roosters territory.
To their credit, the Warriors muscled up after mistakes, responding quickly to ensure there was no further damage.
But the visitors made the worst start to the second half, with Reece Walsh sending the kickoff dead, an almost inexcusable error.
After the Roosters had levelled through a Sam Walker penalty, Walsh was involved in another flashpoint, as he surged over the line, before Jesse Arthars grounded the loose ball.
It looked like a strip but the bunker ruled differently and a 12-point swing was confirmed minutes later, when Kevin Naiqama crossed after Dallin Watene-Zelezniak couldn't defuse a Luke Keary bomb.
That put wind into the Roosters' sails, and they looked increasingly dangerous, especially on short-side raids. Only a brilliant intervention from Watene-Zelezniak on Sitili Tupouniua stopped a certain try, before Walker spun past Johnson and Arthars to score on the hour.
The Warriors managed their play of the season, with some Walsh magic creating a try for Watene-Zelezniak. Walsh beat three defenders as he ran off a Johnson inside ball, before a freakish kick on the run found his winger.
That set up a grandstand finish, before the officials did their best to get in the way. The bunker made one of the most inexplicable calls of the year to give the Roosters possession from the kickoff – after a clear strip on Addin Fonua-Blake. Moments later an obvious Roosters forward pass was missed, before they found a knock-on from Watene-Zelezniak on scratchy evidence.
That culminated in a 71st minute Walker penalty, which extended the lead to eight points and the Roosters managed the game from there.
Roosters 22 (Daniel Tupou, Kevin Naiqama, Sam Walker tries; Walker 3 cons, 2 pens)
Warriors 14 (Ed Kosi, Dallin Watene-Zelezniak tries; Reece Walsh 2 cons, pen)
Halftime: 6-8