You can use a <<goto>> macro to forward the story to the next passage,
The following is a modified variation of your own example to which I have added a conditional <<goto>> macro call, I also slightly changed how the error reporting is implemented.
1) What's the name of the main character?
<<textbox "$player" $player>> \
2) What is the name of the female lead?
<<textbox "$fcname" $fcname>> \
3) What is the name of the town you grew up in?
<<textbox "$townname" $townname>> \
4)What is the name of the city for later use?
<<textbox "$cityname" $cityname>>
<<button "Confirm">>
<<set $player to $player.trim()>>
<<set $fcname to $fcname.trim()>>
<<set $townname to $townname.trim()>>
<<set $cityname to $cityname.trim()>>
<<replace "#error">><</replace>>
<<set _errors to []>>
<<if $player is "">>
<<set _errors.push("a main character name")>>
<</if>>
<<if $fcname is "">>
<<set _errors.push("a female lead name")>>
<</if>>
<<if $townname is "">>
<<set _errors.push("a town name")>>
<</if>>
<<if $cityname is "">>
<<set _errors.push("a city name")>>
<</if>>
<<if _errors.length > 0>>
<<replace "#error">>Please enter <<print _errors.join(', ')>>!<</replace>>
<<else>>
<<goto "Target Passage Name">>
<</if>>
<</button>>\
<span id="error"></span>
note: The above example assumes two things:
1. That you have previously initialised the four story variables, hopefully within you project's StoryInit special passage.
<<set $player to "">>
<<set $fcname to "">>
<<set $townname to "">>
<<set $cityname to "">>
2. That you as using CSS like the following within your project's Story Stylesheet area to correctly add a margin between the "Confirm" button and the area used to display the errors.
#error {
margin-left: 2em;
}