Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Bash & Python Automation By James Joyner IV · · 7 min read Last reviewed Jul 2026

Bash Error Guide: 'event not found' — Fix History Expansion with '!'

Quick answer

Fix Bash '!: event not found': stop history expansion eating '!' in double-quoted strings by using single quotes, escaping, or disabling histexpand.

  • #bash
  • #automation
  • #troubleshooting
  • #errors
Free toolkit

Stuck on this Bash & Python Automation error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

Bash prints event not found when history expansion sees a ! it interprets as a reference to a past command that doesn’t exist:

bash: !doctype: event not found

In an interactive shell, ! is the history-expansion character: !! reruns the last command, !42 recalls history entry 42, !ssh recalls the last command starting with ssh. When a ! appears in a double-quoted string followed by non-whitespace, Bash tries to expand it as a history event — and if no match exists, it aborts with event not found before your command ever runs. Single quotes are immune; double quotes are not.

Symptoms

  • A command containing ! (a password, a URL fragment, HTML like <!DOCTYPE>, a shell negation in text) fails with event not found.
  • It happens at the interactive prompt or in scripts run with history expansion on, but not in plain non-interactive script execution.
  • echo "hello!world" errors, while echo 'hello!world' works.
  • Pasting a strong password containing ! into a curl -u or git command breaks.

Common Root Causes

  • ! inside double quotes followed by a word"Deploy done!" at end of string is usually fine, but "!important" or "a!b" triggers expansion.
  • Passwords or tokens containing ! used unquoted or double-quoted on the command line.
  • HTML/XML with <! or !DOCTYPE echoed or heredoc’d in double quotes.
  • History expansion enabled in a scriptset -H (on by default in interactive shells; off in non-interactive, but some invocations enable it).
  • ! immediately before {, letters, or digits, which look like history references.

Diagnostic Workflow

Confirm history expansion is the mechanism:

echo "$-"          # a 'H' in the flags means histexpand is on
shopt -o -p 2>/dev/null | grep histexpand

Show that quoting changes the behavior:

echo 'value!here'      # works: single quotes disable history expansion
echo "value!here"      # bash: !here: event not found

For scripts, verify how they’re invoked — history expansion is normally off for bash script.sh, but on in bash -i or interactive sourcing.

Example Root Cause Analysis

An operator ran a one-liner to set a database password:

psql -c "ALTER USER app PASSWORD 'S3cr!tPass';"

It failed instantly:

bash: !tPass': event not found

The ! inside the double-quoted argument was interpreted as a history reference (!tPass), which didn’t exist. The command never reached psql. Because the surrounding quoting was double, history expansion fired first. The fixes:

# Option A: turn off history expansion for this shell
set +H
psql -c "ALTER USER app PASSWORD 'S3cr!tPass';"

# Option B: escape the bang
psql -c "ALTER USER app PASSWORD 'S3cr\!tPass';"

# Option C: keep the whole argument in single quotes where possible
psql -c 'ALTER USER app PASSWORD '"'"'S3cr!tPass'"'"';'

For interactive ops work, set +H is the least error-prone; for scripts, prefer single quotes around any value that may contain !.

Prevention Best Practices

  • Use single quotes for strings containing ! — they suppress history expansion entirely.
  • Disable history expansion when it’s not needed — set +H in interactive sessions or at the top of scripts that echo !-heavy text.
  • Escape the bang\! inside double quotes prevents expansion of that character.
  • Keep secrets out of the command line — read passwords from files, env vars, or prompts (read -rs) to avoid quoting hazards and shell-history leakage.
  • In non-interactive scripts, remember history expansion is off by default; the problem is mostly an interactive and bash -i concern.
  • Prefer here-documents with a quoted delimiter (<<'EOF') for large text blocks containing !.

Quick Command Reference

echo 'text!with!bang'      # single quotes: no history expansion
set +H                     # disable history expansion for this shell
echo "text\!with\!bang"    # escape the bang inside double quotes
echo "$-"                  # check for 'H' flag (histexpand on)
read -rs -p 'Password: ' PW   # read secrets without quoting them on the CLI
cat <<'EOF'                # quoted delimiter: literal !, no expansion
<!DOCTYPE html>
EOF

Conclusion

event not found is Bash history expansion mistaking a ! in your command for a reference to a past command. It bites interactive ops work with passwords, URLs, and HTML in double quotes. Reach for single quotes around !-bearing values, set +H to disable expansion when you don’t need it, or \! to escape a single bang. Keeping secrets off the command line entirely sidesteps both this error and leaking them into shell history.

Free download · 368-page PDF

Fixed it? Get 500 Bash & Python Automation & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.