Bash Script Syntax Error Near Unexpected Token `then` or `fi`
Quick answer
"Syntax error near unexpected token" for then or fi almost always means Bash's parser reached that keyword in a context where the surrounding if statement's...
"Syntax error near unexpected token" for then or fi almost always means Bash's parser reached that keyword in a context where the surrounding if statement's structure doesn't actually match what Bash requires — a missing semicolon, a missing or extra keyword, or mismatched conditional syntax earlier in the same statement.
The Problem
A script with what looks like a normal if statement fails to run at all:
./script.sh: line 5: syntax error near unexpected token `then'
./script.sh: line 5: `if [ "$status" = "active" ] then'
Or a similar error referencing fi instead, depending on exactly where the structural mistake occurred.
Why It Happens
Bash's if statement has a specific required structure, and several common, easy-to-make mistakes violate it in ways that produce this exact error:
- Missing the semicolon (or newline) before
then— Bash requiresthento start a genuinely new statement, and without a semicolon or line break separating the condition fromthenon the same line, Bash doesn't recognize where the condition ends and thethenclause begins - A missing closing bracket, brace, or parenthesis in the condition itself, causing Bash to still be "inside" the condition expression when it unexpectedly encounters
then, which it wasn't expecting yet - Missing a corresponding
fito close an earlierifblock, causing a later, unrelatedfi(or the natural end of the script) to be reached in a state Bash doesn't recognize as valid - Mismatched or incorrect conditional test syntax — using
[[ ]]and[ ]inconsistently, or a missing space around brackets, which is required in Bash's test syntax
The Fix
For the semicolon issue, add a semicolon before then when it's on the same line as the condition, or put then on its own new line instead:
# Correct - semicolon before then
if [ "$status" = "active" ]; then
echo "Active"
fi
# Also correct - then on its own line, no semicolon needed
if [ "$status" = "active" ]
then
echo "Active"
fi
For missing brackets or braces in the condition, carefully count and match every opening and closing element in the condition itself:
# Missing closing bracket - causes this exact error
if [ "$status" = "active"; then
# Correct
if [ "$status" = "active" ]; then
For a missing fi, review the entire script for every if and confirm each one has a corresponding, correctly placed fi — for scripts with many nested conditionals, careful indentation makes mismatched or missing fi statements much easier to visually spot:
if [ condition1 ]; then
if [ condition2 ]; then
echo "both true"
fi # closes condition2's if
fi # closes condition1's if
For test syntax consistency, ensure spaces surround every bracket in [ ] test expressions — this is a hard requirement in Bash's syntax, not merely a style preference, and its absence produces exactly this kind of parsing error:
# Incorrect - missing required spaces around brackets
if ["$status" = "active"]; then
# Correct - spaces are mandatory
if [ "$status" = "active" ]; then
If you're using [[ ]] (Bash's extended test syntax, offering additional features over the more portable, POSIX-compliant [ ]), confirm you're consistent within a single condition and not accidentally mixing the two syntaxes together, which produces its own confusing parsing errors:
# Correct, consistent use of [[ ]]
if [[ "$status" == "active" ]]; then
Still Not Working?
If the error persists despite reviewing the specific line referenced, remember that Bash's reported line number sometimes points to where the parser finally noticed something was wrong, not necessarily where the actual mistake originally occurred — a missing fi several lines earlier, for example, can cause an error to be reported much further down the script, at whatever point Bash's parser state finally became irreconcilable. Use bash -n script.sh to check syntax without actually executing the script, and consider using an editor with Bash syntax highlighting, which visually makes structural mismatches (mismatched brackets, missing keywords) much easier to spot than reading plain, unhighlighted text alone:
bash -n script.sh
# reports syntax errors without running the script, useful for iterative debugging