Match ends, Bristol City 2, Charlton Athletic 1.
Josh Brownhill scored a dramatic 98th-minute winner as 10-man Bristol City came from behind to beat Charlton and go fourth in the Championship.
The game looked destined to finish as a draw until midfielder Brownhill latched on to substitute Kasey Palmer's lofted pass and drilled a left-foot shot past Charlton keeper Dillon Phillips.
After a lacklustre first half, the Addicks took the lead when Macauley Bonne beat Daniel Bentley to Beram Kayal's through ball at the corner of the box, took the ball past the Robins keeper and slid it home from a tight angle.
But Bristol City levelled when the visitors failed to cut out a looping cross by Brownhill and another substitute, Famara Diedhiou, headed home from close range.
The Senegal striker was then shown a straight red card four minutes from time for kicking out at Jason Pearce while the Charlton defender was on the floor.
Before Brownhill's late winner, Bristol City looked set to slip to 10th. Instead, they moved within three points of leaders West Bromwich Albion and are only behind third-placed Sheffield Wednesday on goal difference.
Brownhill registered the only effort on target - a tame long-range shot - of a cagey first half, which was interrupted by injuries to Charlton midfielders Sam Field and Jake Forster-Caskey.
But there was no shortage of chances after the break, with Bonne curling a shot wide of the far post and Kayal and Conor Gallagher both being denied by Bentley.
Bonne's opener on the counter-attack came after the home side's best spell of pressure as Andi Weimann saw a shot from eight yards turned over the bar by Phillips, while Diedhiou and Rodri both had efforts scrambled off the line following a corner.
Phillips then pulled off two more fine stops to keep out a fierce Weimann drive and a Palmer header, before Diedhiou nodded in the equaliser.
Brownhill then popped up in the box to slam home to winner and spark wild celebrations around Ashton Gate.
Bristol City head coach Lee Johnson told BBC Radio Bristol:
"It's an unbelievable feeling. I'm not sure if it trumps the Manchester United feeling (after beating them in the League Cup quarter-finals in 2017).
"Charlton are a good side and you can see why they've picked up a lot of results in the Championship.
"I knew I was going to get the howls when I made the sub (Diedhiou for Niclas Eliasson) because I understood that it wouldn't have looked like it made sense. I wanted to match them with a diamond and get width from our full-backs. I'm so pleased of the quality and the bravery to keep playing in the second half."
Charlton manager Lee Bowyer told BBC Radio London:
"I thought we deserved to win so to come away with nothing is hard for the lads. I can't fault them as they gave everything.
"We have to learn from this, because we have to be more ruthless.
"We got into so many good areas in the first half and we didn't punish them - and they are a good side. I am gutted.
"In this league this is what happens - if you don't take your chances then you always give the others a chance to come back into it."
- 32Lopes PereiraBooked at 83mins
- 19EliassonSubstituted forRíos Lozanoat 54'minutes
- 42MassengoSubstituted forPalmerat 69'minutes
- 14WeimannBooked at 90mins
- 18SemenyoSubstituted forDiédhiouat 54'minutesBooked at 86mins
- 31Ríos Lozano
- 1PhillipsBooked at 85mins
- 8Forster-CaskeySubstituted forSollyat 36'minutes
- 28FieldSubstituted forPratleyat 33'minutesBooked at 55mins
- 21KayalBooked at 14minsSubstituted forAnekeat 72'minutesBooked at 90mins
- 17BonneBooked at 90mins
- James Linington
- Shots on Target
Second Half ends, Bristol City 2, Charlton Athletic 1.
Goal! Bristol City 2, Charlton Athletic 1. Josh Brownhill (Bristol City) left footed shot from the centre of the box to the bottom left corner. Assisted by Kasey Palmer with a through ball.
Andreas Weimann (Bristol City) is shown the yellow card.
Attempt missed. Callum O'Dowda (Bristol City) left footed shot from outside the box is too high following a corner.
Corner, Bristol City. Conceded by Chris Solly.
Chuks Aneke (Charlton Athletic) is shown the yellow card.
Kasey Palmer (Bristol City) wins a free kick on the right wing.
Foul by Chuks Aneke (Charlton Athletic).
Kasey Palmer (Bristol City) wins a free kick in the defensive half.
Foul by Conor Gallagher (Charlton Athletic).
Macauley Bonne (Charlton Athletic) is shown the yellow card.
Offside, Charlton Athletic. Darren Pratley tries a through ball, but Macauley Bonne is caught offside.
Foul by Taylor Moore (Bristol City).
Macauley Bonne (Charlton Athletic) wins a free kick in the defensive half.
Attempt missed. Andreas Weimann (Bristol City) left footed shot from the right side of the box misses to the left.
Rodri (Bristol City) wins a free kick in the defensive half.
Foul by Josh Cullen (Charlton Athletic).
Famara Diédhiou (Bristol City) is shown the red card for violent conduct.
Foul by Famara Diédhiou (Bristol City).