Why Sponsor Oils? | source | all docs for version 0.37.0 | all versions | oils.pub
This doc lists errors from Oils (both OSH and YSH), with hints to help you fix them.
Each error is associated with a code like OILS-ERR-42, a string that search
engines should find.
If you see an error that you don't understand:
#oil-help on Zulip. What's the problem,
and what's the solution?grep the source code for the confusing error message. Tag it with a
string like OILS-ERR-43, picking a new number according to the conventions
below.doc/error-catalog.sh, or
test/{parse,runtime,ysh-parse,ysh-runtime}-errors.sh. Add an HTML
comment <!-- --> about that.Note that error messages are hard to write, because a single error could result from many different user intentions!
Right now I use this command:
build/doc.sh split-and-render doc/error-catalog.md
Then paste this into your browser:
file:///home/andy/git/oils-for-unix/oils/_release/VERSION/doc/error-catalog.html
(Replace with your home dir)
Roughly speaking, a parse error means that text input was rejected, so the shell didn't try to do anything.
Examples:
echo ) # Shell syntax error
type -z # -z flag not accepted
These error codes start at 10.
setvar x = true
^
[ -c flag ]:3: setvar couldn't find matching 'var x' (OILS-ERR-10)
Related help topics:
echo $'\z'
^
[ -c flag ]:1: Invalid char escape in C-style string literal (OILS-ERR-11)
$'\\z'? Backslashes must be escaped in $'' and u'' and
b'' strings.$'\n'? Only valid escapes are accepted in YSH.Related help topics:
echo "\z"
^
[ -c flag ]:1: Invalid char escape in double quoted string (OILS-ERR-12)
"\\z"? Backslashes must be escaped in double-quoted strings."\$"? Only valid escapes are accepted in YSH.u'\n' rather than u"\n"?Related help topics:
echo \z
^~
[ -c flag ]:1: Invalid char escape in unquoted word (OILS-ERR-13)
\\z? Backslashes must be escaped in unquoted words.\$? Only valid escapes are accepted in YSH. if ((1 > 0 && 43 > 42)); then echo yes; fi
^~
[ -c flag ]:1: Bash (( not allowed in YSH (no_parse_dparen, see OILS-ERR-14 for wart)
Two likely causes:
Examples:
if (1 > 0 and 43 > 42) { # YSH-style
echo yes
}
if ( (x + 1) < n) { # space between ( ( avoids ((
echo yes
}
if (a || b && c) {
^~
[ -c flag ]:2: Use 'or' in expression mode (OILS-ERR-15)
Expression mode uses not or and, rather than ! || &&. See Command vs.
Expression Mode for details.
No:
if (!a || b && c) {
echo no
}
Yes:
if (not a or b and c) {
echo yes
}
Command mode is the opposite; it uses ! || &&, rather than not or and:
No:
# Command mode
if not test --dir a or test --dir b and test --dir c {
echo no
}
Yes:
# Command mode
if ! test --dir a || test --dir b && test --dir c {
echo yes
}
for x in (1 .. 5) {
^~
[ -c flag ]:1: Use ..< for half-open range, or ..= for closed range (OILS-ERR-16)
There are two ways to construct a Range. The ..<
operator is for half-open ranges and the ..= operator is for closed ranges:
for i in (0 ..< 3) {
echo $i
}
=> 0
=> 1
=> 2
for i in (0 ..= 3) {
echo $i
}
=> 0
=> 1
=> 2
=> 3
echo --flag=u'foo'
^
[ -c flag ]:1: Invalid quoted word part in YSH (OILS-ERR-17)
In YSH, --flag='foo' is allowed, but --flag=u'foo\n' is not. In the latter
case, it's not clear if the u is literal.
Try one of these alternatives:
ysh$ echo u'--flag=foo\n' # quote the whole thing
ysh$ echo --flag u'foo\n' # space instead of =
ysh$ echo --flag=$myvar # assign to variable first
ysh$ echo $['--flag=' ++ myvar] # expression sub
echo "date = `date`"
^
[ -c flag ]:1: Backtick should be $(cmd) or \` (no_parse_backticks, OILS-ERR-18)
$(date) instead?
\`?
\`.) ( cd /tmp && ls )
^
[ -c flag ]:1: Subshell syntax ( ) isn't allowed in YSH (OILS-ERR-19)
forkwait { echo hi } to create a subshell.cd /tmp { ls } to save
and restore state.Note that, in shell, the ( ) syntax does not simply group commands. The
{ } syntax is for grouping commands.
This is a common mistake because parentheses are for grouping in other programming languages.
var x = ' \n '
^~~~
[ -c flag ]:1: Ambiguous backslash: add explicit r'' or u'' prefix (OILS-ERR-20)
Did you mean r' \n '? This is a raw string with a literal backslash.
Or did you mean u' \n ' or b' \n '? These are strings with C-style
escapes.
YSH wants you to be explicit about what backslashes mean.
These errors may occur in shells like bash and zsh.
They're numbered starting from 100. (If we have more than 90 parse errors,
we can start a new section, like 300.)
findz
^~~~~
[ -c flag ]:1: Command 'findz' not found (OILS-ERR-100)
The shell tried to execute an external command, but couldn't.
proc?$PATH? The PATH variable is a colon-separated list
of directories, where executable files may live.findz file executable bit set? (chmod +x)Let's look at three instances of this error.
declare -A assoc; assoc[x]=1
^~~~~~
[ -c flag ]:1: fatal: Assoc array keys must be strings: $x 'x' "$x" etc. (OILS-ERR-101)
x a string? Then add quotes: assoc['x']=1x a variable? Then write: assoc[$x]=1Same idea here:
declare -A assoc; echo ${assoc[x]}
^
[ -c flag ]:1: fatal: Assoc array keys must be strings: $x 'x' "$x" etc. (OILS-ERR-101)
x a string? Then add quotes: ${assoc['x']}x a variable? Then write: ${assoc[$x]}The third example is tricky because unset takes a string. There's an
extra level of parsing, which:
assoc[k]
^
[ dynamic LHS word at line 1 of [ -c flag ] ]:1
declare -A assoc; key=k; unset "assoc[$key]"
^
[ -c flag ]:1: fatal: Assoc array keys must be strings: $x 'x' "$x" etc. (OILS-ERR-101)
To fix it, consider using single quotes:
unset 'assoc[$key]'
var cmd = ^(seq 3)
^~~
[ stdin ]:1: Command 'seq' not found in pure mode (OILS-ERR-102)
The shell tried to execute a command in pure mode, but couldn't.
In pure mode, only user-defined procs and a few builtin commands can be the "first word".
These errors don't occur in shells like bash and zsh.
They may involve Python-like expressions and typed data.
They're numbered starting from 200.
cat ("myfile")
^
[ -c flag ]:1: fatal: 'cat' appears to be external. External commands don't accept typed args (OILS-ERR-200)
= "age: " + "100"
^
[ -c flag ]:1: fatal: Binary operator expected numbers, got Str and Str (OILS-ERR-201)
= 100 + myvar
^
[ -c flag ]:2: fatal: Binary operator expected numbers, got Int and Str (OILS-ERR-201)
++ to concatenate strings/lists?int() or
float(). pp (42.0 === x)
^~~
[ -c flag ]:3: fatal: Equality isn't defined on Float values (OILS-ERR-202)
Floating point numbers shouldn't be tested for equality. Alternatives:
= abs(42.0 - x) < 0.1
= floatEquals(42.0, x)
var mylist = [1,2,3]; write $[mylist]
^~
[ -c flag ]:1: fatal: Expr sub got a List, which can't be stringified (OILS-ERR-203)
@mylist instead of $mylist?@[myfunc()] instead of $[myfunc()]?$[join(mylist)]?Or:
['good', {bad: true}]? x=$(date)
^~
impure.sh:1: fatal: Command subs aren't allowed in pure mode (OILS-ERR-204)
In pure mode, the shell can't do I/O. It's intended for config file evaluation and pure functions.
--eval instead of --eval-pure?proc, rather than a func?strict:all if ! ls | wc -l; then echo failed; fi
^
[ -c flag ]:1: fatal: Command conditionals should only have one status, not Pipeline (strict_errexit, OILS-ERR-300)
Compound commands can't be used as conditionals because it's ambiguous.
It confuses true/false with pass/fail. What if part of the pipeline fails?
What if ls doesn't exist?
This YSH idiom is more explicit:
try {
ls | wc -l
}
if failed {
echo failed
}
if shell-func; then
^~~~~~~~~~
foo.sh:9: fatal: Can't run functions or procs while errexit is disabled (OILS-ERR-301)
This error prevents you from hitting a pitfall with set -e aka errexit,
as it's defined in POSIX shell.
Here are some shell-compatible solutions:
if, ||, etc.if $0 shell-func
In YSH, use the try builtin instead of if.
errexit) FOO=bar eval 'echo FOO=$FOO'
^~~~
[ stdin ]:3: fatal: Special builtins can't have prefix bindings (OILS-ERR-302)
In POSIX shell, prefix bindings have two behaviors:
This is invisible and confusing, so YSH has shopt --set strict_env_binding to
make the first meaning the only one.
Try this instead:
var FOO = 'bar'
eval 'echo FOO=$FOO'
echo hi > /does/not/existerror builtin (status 10 is default)(If you updated this doc, feel free to add your name to the end of this list.)