fish-shell/fish-shell · error
%s
Error message
%s
What it means
When a `function` definition statement fails, run_function_statement runs the function builtin, captures its exit status and any text written to the error stream, and re-raises the builtin's message through report_error! using the format string '%s' with the captured error text. The '%s' is the error's format template, not the actual message; the real diagnostic (e.g. 'function: name should be one word') is in errtext.
Source
Thrown at src/parse_execution.rs:1319
return result;
}
trace_if_enabled_with_args(ctx.parser(), L!("function"), &arguments);
let mut outs = OutputStream::Null;
let mut errs = OutputStream::String(StringOutputStream::new());
let io_chain = IoChain::new();
let mut streams = IoStreams::new(&mut outs, &mut errs, &io_chain);
let mut shim_arguments: Vec<&wstr> = arguments
.iter()
.map(|s| truncate_at_nul(s.as_ref()))
.collect();
let err_code = builtins::function::function(
ctx.parser(),
&mut streams,
&mut shim_arguments,
NodeRef::new(Arc::clone(self.pstree()), statement),
)
.err()
.unwrap_or(STATUS_CMD_OK);
ctx.parser().libdata_mut().status_count += 1;
ctx.parser().set_last_statuses(Statuses::just(err_code));
let errtext = errs.contents();
if !errtext.is_empty() {
report_error!(self, ctx, err_code, header, "%s", errtext);
}
result
}
fn run_begin_statement(
&mut self,
ctx: &mut OperationContext<'_>,
contents: &ast::JobList,
) -> EndExecutionReason {
// Basic begin/end block. Push a scope block, run jobs, pop itView on GitHub (pinned to edb719d76c)
Solutions
- Read the accompanying diagnostic line printed with this error for the actual cause
- Ensure the function name is a single valid word (letters/digits/underscore, not starting with a dash, no path separators)
- If the name comes from a variable, quote and validate it before `function $name`, e.g. `function $name; ...` only when `string match -qr '^[A-Za-z_][A-Za-z0-9_]*$' -- $name`
- Check that all arguments on the function header line expand correctly and don't contain wildcards that match nothing
Example fix
// before
function $fname; echo hi; end # fname empty -> error
// after
if set -q fname[1]; and string match -qr '^[A-Za-z_][A-Za-z0-9_]*$' -- $fname
function $fname; echo hi; end
end Defensive patterns
Strategy: try-catch
Validate before calling
if not string match -qr '^[A-Za-z_][A-Za-z0-9_]*$' -- $fname
echo "invalid function name: $fname" >&2
exit 1
end Type guard
function is_valid_function_name
string match -qr '^[A-Za-z_][A-Za-z0-9_]*$' -- $argv[1]
end Try / catch
// fish has no try/catch for parse errors; capture and inspect status
function define_fn --argument-names name
eval "function $name; end" 2>/tmp/fnerr
or begin
cat /tmp/fnerr >&2
return 1
end
end Prevention
- Validate expanded function names before `function` statements
- Avoid variable names in function headers sourced from user input
- Don't name functions after reserved words or paths
- Lint sourced scripts with `fish --no-execute` to catch definitions early
When it happens
Trigger: Executing a `function NAME ...; end` statement where the function builtin returns an error status: invalid function name (not a valid identifier / contains slashes), duplicate reserved names, missing name, or arguments failing expansion.
Common situations: Sourcing an old script whose function name collides with fish's reserved/invalid names, `function` with a variable-expanded name that expands to an empty string or multiple words, or copy-pasted zsh/bash function syntax invalid in fish.
Related errors
- %s: expected a numeric value
- %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
AI-assisted analysis of fish-shell/fish-shell@edb719d76c (2026-09-03).
Data as JSON: /api/errors/a0155814d16289bd.
Report an issue: GitHub.