fish-shell/fish-shell · error
%s: expected a numeric value
Error message
%s: expected a numeric value
What it means
Raised by the printf builtin (src/builtins/printf.rs:219) in verify_numeric when nothing at all was consumed from the argument: the end slice still points at the start of s (s.as_ptr() == end.as_ptr()) and no converter error code was set. It means the argument to a numeric directive (%d, %f, %x, ...) does not begin with anything numeric. This is fatal: printf stops processing and exits with an error status.
Source
Thrown at src/builtins/printf.rs:219
impl<'a, 'b> State<'a, 'b> {
#[allow(clippy::partialeq_to_none)]
fn verify_numeric(&mut self, s: &wstr, end: &wstr, errcode: Option<wutil::Error>) {
// This check matches the historic `errcode != EINVAL` check from C++.
// Note that empty or missing values will be silently treated as 0.
if errcode.is_some_and(|err| err != wutil::Error::InvalidChar && err != wutil::Error::Empty)
{
match errcode.unwrap() {
wutil::Error::Overflow => {
self.fatal_error(err_fmt!("%s: Number out of range", s));
}
wutil::Error::InvalidChar | wutil::Error::Empty => {
unreachable!("Unreachable");
}
}
} else if !end.is_empty() {
if s.as_ptr() == end.as_ptr() {
self.fatal_error(err_fmt!("%s: expected a numeric value", s));
} else {
// This isn't entirely fatal - the value should still be printed.
self.nonfatal_error(err_fmt!(
"%s: value not completely converted (can't convert '%s')",
s,
end
));
// Warn about octal numbers as they can be confusing.
// Do it if the unconverted digit is a valid hex digit,
// because it could also be an "0x" -> "0" typo.
if s.char_at(0) == '0' && iswxdigit(end.char_at(0)) {
self.nonfatal_error(err_str!(
"Hint: a leading '0' without an 'x' indicates an octal number"
));
}
}
}
}View on GitHub (pinned to a1e92997a1)
Solutions
- Validate the value before printf: `string match -qr '^-?[0-9]+(\.[0-9]+)?$' -- $val` and reject/skip otherwise
- Use fish's `math` builtin or `read` with validation instead of printf numeric coercion for untrusted input
- Print untrusted data with %s and only use numeric directives for values your script produced
- Check the variable is set and non-empty first: empty values are silently treated as 0, which can mask upstream bugs
Example fix
# before
printf '%d' $maybe_number # abc: expected a numeric value
# after
if string match -qr -- '^-?[0-9]+$' $maybe_number
printf '%d' $maybe_number
else
echo "not a number: $maybe_number" >&2
end Defensive patterns
Strategy: validation
Validate before calling
# only hand provably-numeric strings to numeric directives
if string match -qr -- '^[+-]?[0-9]+(\.[0-9]+)?([eE][+-]?[0-9]+)?$' $value
printf '%f\n' $value
else
echo "skipping non-numeric: $value" >&2
end Type guard
function is_numeric
string match -qr -- '^[+-]?([0-9]+(\.[0-9]*)?|\.[0-9]+)([eE][+-]?[0-9]+)?$' $argv[1]
end Prevention
- Validate externally-sourced values with string match -r before printf
- Remember empty strings are silently treated as 0 — check set -q separately if empty is an error
- Prefer %s plus your own formatting when the input's shape is unknown
When it happens
Trigger: Running `printf %d abc`, `printf %f NaN_variable`, or `printf %x 0x` where the parse consumes zero characters. Reached when errcode is None/InvalidChar/Empty but end is non-empty and unchanged; i.e. wcstoi_partial/wcstod returned consumed == 0 with no hard error. Note the leading-quote form `printf %f "'a"` bypasses this via from_ord.
Common situations: Unquoted or wrongly-parsed variables feeding printf format strings; scripts assuming an environment variable always holds a number; user input not validated; a subtle case is locale issues with decimal separators for %f, though fish retries with '.' before giving up (see the wcstod fallback in RawStringToScalarType).
Related errors
- %s: value not completely converted (can't convert '%s')
- Hint: a leading '0' without an 'x' indicates an octal number
- %s: Number out of range
- Number out of range
- %s
AI-assisted analysis of fish-shell/fish-shell@a1e92997a1 (2026-08-17).
Data as JSON: /api/errors/2a7f15c3d7629968.
Report an issue: GitHub.