Silent Killer: unknown flag or subcommand " "
Some errors are loud.
A segfault is loud. A panic is loud. A stack trace is loud.
You know exactly where to look.
And then there are silent killers.
Not silent because they don’t produce errors. Silent because they produce errors that point you in the wrong direction.
This is one of them:
error: unknown flag or subcommand " "
At first glance, this looks like:
- your CLI parser is broken
- your flags are malformed
- your binary isn’t handling input correctly
- maybe even something weird with how Bash is invoking the command
It looks like a system problem.
It is not.
The Setup
You’re writing a multi-line command because it’s getting long:
~/gh/fmc/fmc \
-exportJSON ./source.json \
-dir ../docusaurus-prod/technical/languages/oop-and-functional/ \
-urlStartsAfter /home/tjr/gh/trones-noters/docusaurus-prod/
Clean. Readable. Exactly how you should be doing it.
Except… it doesn’t work.
Instead, you get:
error: unknown flag or subcommand " "
The Actual Problem
This line:
-exportJSON ./source.json \
Look closely.
There is a space after the backslash.
That’s it. That’s the entire bug.
Why This Breaks
In Bash, the backslash (\) is a line continuation character.
But only if it is:
the last character on the line
This works:
\⏎
This does not:
\ ⏎
That trailing space cancels the continuation.
So instead of one command, Bash interprets this as:
~/gh/fmc/fmc -exportJSON ./source.json " "
Yes — an actual argument that is literally a single space.
Your binary receives:
["-exportJSON", "./source.json", " "]
And your CLI does exactly what it should do:
unknown flag or subcommand " "
The system is correct.
But the error is cognitively misleading.
Why This Is a Silent Killer
This bug is powerful because it breaks multiple assumptions at once:
1. The character is invisible
You cannot see it unless you’re specifically looking for it.
2. The failure happens downstream
The shell misinterprets your command, but the error shows up in your application layer.
3. The error message is technically correct
Your program did receive " " as an argument.
But that is not how your brain models the problem.
4. It sends you searching in the wrong place
You start thinking about:
- flag parsing
- CLI frameworks
- argument ordering
- quoting issues
- maybe even rebuilding the binary
None of those are the problem.
First Move: Check for Invisible Characters
When you see an error that:
- doesn’t match your mental model
- doesn’t make sense given what you’re looking at
- or seems to implicate the wrong layer
One of the first things you should do is:
Assume there are characters you are not seeing
Most editors do not render:
- trailing spaces
- control characters
- carriage returns
- subtle whitespace differences
So what you think you wrote and what the system received can diverge.
CLI: What the Machine Actually Sees
cat -A my_script.sh
This shows:
$→ end of line- visible trailing spaces
- control characters
In my case, this made the issue obvious:
- the backslash was followed by a space
- then the end of line
Which means the line continuation never happened.

VS Code: What You Thought You Saw
By default, VS Code hides this completely.
Use the quick toggle:
Ctrl + Shift + P
→ Toggle Render Whitespace
Now the editor shows:
- spaces as dots
- trailing whitespace clearly
- alignment differences that actually matter
Which immediately reveals the problem.

The Gap
Here’s the important part:
The bug was not in the logic. The bug was in the representation.
- VS Code (default): shows intent
cat -A: shows reality
And debugging lives in the gap between those two.
The Heuristic
When something feels off:
- Don’t assume your logic is wrong
- Don’t assume the tool is broken
- First check:
“Am I actually passing the characters I think I am?”
The Fix
Remove the trailing space so the backslash is the final character:
~/gh/fmc/fmc \
-exportJSON ./source.json \
-dir ../docusaurus-prod/technical/languages/oop-and-functional/ \
-urlStartsAfter /home/tjr/gh/trones-noters/docusaurus-prod/
That’s it.
A Better Pattern (Optional)
If you want to eliminate this entire class of bugs:
ARGS=(
-exportJSON ./source.json
-dir ../docusaurus-prod/technical/languages/oop-and-functional/
-urlStartsAfter /home/tjr/gh/trones-noters/docusaurus-prod/
)
~/gh/fmc/fmc "${ARGS[@]}"
No backslashes. No continuation rules. No invisible failure modes.
The Real Lesson
This is not about Bash.
This is about where bugs hide.
The most time-consuming bugs are not always:
- complex algorithms
- distributed systems issues
- concurrency problems
Sometimes they are:
low-entropy problems with high misdirection
A single character.
In a place your eyes were never trained to inspect.
Closing Thought
The system didn’t fail.
The system did exactly what you told it to do.
You just didn’t realize what you told it.
And that’s what makes it a silent killer.