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: 'printf: invalid number' — Fix Numeric Format Args

Quick answer

Fix Bash 'printf: invalid number': strip whitespace and non-digits before %d, validate input, and use %s or bc for decimals printf can't format.

  • #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’s printf prints invalid number when a value handed to a numeric conversion (%d, %i, %x, %o) isn’t a valid integer:

./stats.sh: line 14: printf: 1,024: invalid number

%d expects a plain integer. Anything with a comma, a decimal point, trailing units, leading/trailing whitespace, or embedded letters makes printf warn invalid number, substitute 0, and continue with a non-zero-ish exit. It’s a data-validation error surfacing at format time — the number you fed in wasn’t the number printf can parse.

Symptoms

  • printf '%d' warns invalid number and prints 0 instead of your value.
  • The value looks numeric to a human (1,024, 3.5, 42%, 12 ) but isn’t a bare integer.
  • Output shows 0 where a count or size should be, corrupting reports and comparisons downstream.
  • It appears when formatting the output of du, df, awk, or an API that returns numbers with separators or units.

Common Root Causes

  • Thousands separators1,024 or 1 024; printf %d only accepts unseparated digits.
  • A decimal/float3.5; %d is integer-only (use %.0f or %s).
  • Trailing units or symbols42%, 12ms, 2G.
  • Leading/trailing whitespace or a stray \r from a CRLF file or command output.
  • Empty value — an unset variable expands to nothing, and %d treats “no argument” or empty as invalid/zero.
  • Locale-formatted numbers where the decimal or grouping character differs.

Diagnostic Workflow

Reveal exactly what’s in the value, including hidden characters:

val="1,024"
printf '%q\n' "$val"        # shows quotes/commas/whitespace/\r escaped

Test whether it’s a clean integer before formatting:

[[ "$val" =~ ^-?[0-9]+$ ]] && echo "int" || echo "not an int: [$val]"

Trace the failing call:

bash -x ./stats.sh 2>&1 | grep -i 'invalid number\|printf'

Example Root Cause Analysis

A capacity report formatted disk usage:

USED=$(df -h /data | awk 'NR==2 {print $3}')   # e.g. "2.3G"
printf 'Used: %d GB\n' "$USED"

It emitted:

report.sh: line 2: printf: 2.3G: invalid number
Used: 0 GB

df -h returns human-readable values (2.3G) with a unit suffix and a decimal — neither valid for %d. Two correct fixes depending on intent. To print the raw string, use %s:

USED=$(df -h /data | awk 'NR==2 {print $3}')
printf 'Used: %s\n' "$USED"        # "Used: 2.3G"

To do integer math, pull machine-readable bytes and let printf/numfmt format:

BYTES=$(df -B1 /data | awk 'NR==2 {print $3}')   # plain integer bytes
printf 'Used: %d bytes (%s)\n' "$BYTES" "$(numfmt --to=iec "$BYTES")"

Now the value passed to %d is a bare integer, and human formatting is handled separately.

Prevention Best Practices

  • Validate before formatting — gate %d behind [[ "$v" =~ ^-?[0-9]+$ ]] and handle non-integers explicitly.
  • Use %s for display when the value carries units or separators you want to keep verbatim.
  • Fetch machine-readable numbersdf -B1, --bytes, or API fields without separators, then format with numfmt/printf.
  • Strip whitespace and \rv=${v//[$'\t\r ']/} or run dos2unix on inputs from Windows.
  • Do decimal math with awk/bc, not printf %d, which truncates and can’t parse floats.
  • Default empty values${v:-0} so an unset variable doesn’t silently become an invalid number.

Quick Command Reference

[[ "$v" =~ ^-?[0-9]+$ ]] || { echo "not int: $v"; exit 1; }  # validate
printf '%s\n' "$v"                    # display value with units as-is
v=${v//,/}                            # strip thousands separators
v=${v//[$'\t\r ']/}                   # strip whitespace and CR
numfmt --to=iec "$bytes"              # format an integer to 2.3G safely
printf '%d\n' "$(( v ))"              # force arithmetic context (ints only)

Conclusion

printf: invalid number means a value bound to %d/%x wasn’t a bare integer — it had a comma, a decimal, a unit, whitespace, or a stray \r. Validate with a regex before formatting, use %s when you want to keep units, and pull machine-readable numbers (df -B1, numfmt) for math. Guard your format arguments and reports stop silently printing 0 where real numbers belong.

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.