Carlos Lee had a two-run double and Jeff Keppinger and Pedro Feliz drove in runs for the Astros, who've won six of eight after an 0-8 start.
Oswalt (2-2) allowed four hits, struck out four and didn't give up a run until his last inning, the seventh. That inning started with Ryan Church's slow bunt that rolled between Oswalt's legs, the Houston ace's first error in 121 starts dating to May 2006.
"My 4-year-old could've caught that ball, that's the bad part about it," Oswalt said. "Just took my eye off of it, kind of came up and was thinking it was an automatic out, instead of fielding the ball and throwing to first."
Oswalt dominated the punchless Pirates' offense to that point, allowing only two hits. The mistake knocked him off his game, though, and he gave up homers to Garrett Jones and Jeff Clement in the inning.
"I kind of let my guard down and got to thinking about the error," Oswalt said. "I started heaving the ball up there, I don't what I was thinking. Just kind of lost my mind there for a second."
Oswalt regrouped and struck out Delwyn Young, moving past J.R. Richard on the Astros' list (1,494). Nolan Ryan is the franchise leader with 1,866.
"When you think of J.R. Richard, you think of strikeouts, for sure," Oswalt said. "Nolan is a long ways away. I don't know if I can catch him."
Brandon Lyon pitched a perfect eighth and Matt Lindstrom shut out Pittsburgh in the ninth to earn his fifth save in five chances this season.
Left-hander Paul Maholm (1-2) gave up four runs on six hits in seven innings, losing for the first time in his last five starts at Minute Maid Park.
But the Pirates seemed upbeat about their effort after a franchise-worst 20-0 loss to Milwaukee on Thursday.
"We battled, and the guys came out ready to play," Maholm said. "The guys knew what they had to do. Yesterday happens some times."
Maholm didn't allow a hit until Oswalt's one-out single in the third inning. One out later, Keppinger ripped a grounder that went through Young's legs at third base for a double and a 1-0 lead.
Oswalt retired nine in a row after Jones' leadoff single in the second. Ryan Doumit led off the fifth with a single, but Oswalt set down the next three hitters, striking out Maholm to end the inning.
Oswalt needed only 11 pitches to breeze through the sixth. Since 2001, Oswalt has pitched at least six innings in 26 consecutive starts against Pittsburgh, the longest active streak in the majors, according to the Elias Sports Bureau. Oswalt also has 26 straight starts of six innings or more against St. Louis.
The Astros stretched the lead to 4-0 in the sixth, after Michael Bourn led off with an infield hit. Keppinger bunted, Young charged in and threw wildly to first base, putting runners on second and third.
One out later, Lee blooped a double down the left-field line. Lee came in with only eight hits and one RBI in 59 at-bats.
Feliz drove in Lee with a ground-rule double that bounced sideways into the seats down the right-field line.
Bourn made a leaping catch on the warning track to end the seventh, and a diving catch on Jones' liner leading off the ninth.
"Just have to believe that you can go get the ball," said Bourn, an Gold Glove winner in 2009. "Sometimes, you might not get to them, but a lot of them I'm going to try to get to. Either way, I'm going to still have my confidence."Notes
The Pirates optioned shortstop Argenis Diaz to Triple-A Indianapolis and recalled right-handed pitcher Chris Jakubauskas before the game. Pittsburgh manager John Russell said Jakubauskas may start Saturday's game against the Astros. The 31-year-old Jakubauskas is 0-2 with a 4.50 ERA in two starts (10 innings pitched) with Indianapolis this season. ... The Astros reinstated RHP Yorman Bazardo from the disabled list (shoulder strain) and outrighted his contract to Triple-A Round Rock. Bazardo has three days to accept the assignment or opt for free agency. ... The Pirates have lost 11 of their last 14 games in Houston. Maholm was the winning pitcher in the three victories.