Skip to main content
DevOps Insightsguides & answers

Bash · troubleshooting

[: too many arguments

A [ ] test received a different number of words than it expects, almost always because a variable was not quoted and was empty or contained spaces. The test fails, and the script carries on down the wrong branch.

Reproduced on bash 5.2.21, . Where the text says “reproduced”, the behaviour was run on that version, not taken from documentation.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 9 sections

Before you start

  • The script line from the error, and the value the variable had.

Run this first

step 1 of 1
bash -x script.sh

Look for + '[' … ']' lines with an empty slot or extra words

Shows each command after expansion, so you see exactly which words [ received.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

Which message?

Cause space

2 of 2 still possible

  • An unquoted variable is empty or contains spacesCommon
  • A numeric comparison got textCommon

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    bash -x script.sh

    Shows each command after expansion, so you see exactly which words [ received.

    Look for + '[' … ']' lines with an empty slot or extra words

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

An unquoted variable is empty or contains spaces

Common

[ $X = prod ] becomes [ = prod ] when X is empty, and [ a b = prod ] when X is "a b".

Confirm

bash -x script.sh 2>&1 | grep '\['

The [ command as it actually ran, with missing or extra words

Fix

  • Quote every variable in [ ]: [ "$X" = "prod" ], [ -f "$F" ].
  • In bash scripts, [[ $X == prod ]] avoids the splitting entirely.
if [ -f "$F" ]; then …

Reproduced on bash 5.2.21: the quoted test found my file.txt.

A numeric comparison got text

Common

-gt, -lt and -eq need integers. Output with a unit, a blank line, or a trailing carriage return is not one.

Confirm

printf '%s' "$V" | od -c | head -2

Characters other than digits, such as \r or a letter

Fix

  • Clean the value before comparing: V=$(printf '%s' "$V" | tr -d '\r[:space:]').
  • Check it is a number first: case $V in ''|*[!0-9]*) echo "not a number: $V" >&2; exit 1;; esac.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Before running [, the shell replaces $VAR with its value and splits it on spaces. An empty variable disappears; a value with a space becomes two words. [ then sees the wrong number of pieces and complains. Put double quotes around every variable in a test.

Words used on this page

Word splitting
The shell splitting an unquoted variable's value on spaces into separate arguments.
[[ ]]
Bash's own test syntax, which does not word-split variables; not available in sh or dash.
What is actually happening

Reproduced on 23 October 2026 with bash 5.2.21 on Ubuntu 24.04 and bash 3.2.57 on macOS. With F="my file.txt", [ -f $F ] printed [: my: binary operator expected. [ $S = "a b" ] with S="a b" printed [: too many arguments, and [ $X = "prod" ] with X empty printed [: =: unary operator expected.

In every case the script kept going: [ returned an error status, the if took its else branch, and the script exited 0. set -e did not stop it, because a command tested by if or && is exempt.

[ "$V" -gt 2 ] with V=abc printed [: abc: integer expression expected. The same happens when a number read from a file or command carries a carriage return from Windows line endings.

How to tell this is your problem
WhereWhat you see
Unquoted variable with spacesscript.sh: line 4: [: too many arguments
Unquoted empty variablescript.sh: line 4: [: =: unary operator expected
Unquoted file name with a spacescript.sh: line 4: [: my: binary operator expected
Numeric test on textscript.sh: line 4: [: abc: integer expression expected

How to know it is actually fixed

  • The test takes the branch you expect for an empty value, a value with spaces, and a normal value.

Stopping it happening again

  • Quote every variable expansion unless you specifically want splitting.
  • Run shellcheck in CI; SC2086 reports unquoted variables.
  • Exit explicitly when a check fails, rather than relying on set -e to catch a failed test.

Security considerations

  • The script does not stop on these errors, even with set -e, so a failed check can let a deploy step run that the check was meant to block. Quote the variables and test the failure path.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it