§ C1 · Track A · Companions

Reading a CUE error

The four parts of a pravo error, the three stages that produce one, and the messages you meet first.

Time
8 min
Level
beginner
Needs
A3
You will learn
Where did pravo stop, which field is it, and which line do you change?
Done when
sh check.sh prints ok after you fixed three mistakes, one error at a time.

View as Markdown

On this page

A CUE error is a path, two values and two file positions, with no instruction. Every error has the same four parts. Once you can find them, the error tells you which line to open.

Work in an empty directory. This page writes its own files. Two files give one field two values.

estate.cue
package estate

buckets: logs: retention_days: 365
team.cue
package estate

buckets: logs: retention_days: 90
terminalexit 6
$pravo eval
Error: evaluating .:
buckets.logs.retention_days: conflicting values 90 and 365:
    ./estate.cue:3:32
    ./team.cue:3:32
Error: evaluating .:  1 stage
buckets.logs.retention_days: conflicting values 90 and 365:  2 path  3 message
    ./estate.cue:3:32  4 locations
    ./team.cue:3:32
fig. 1 The four parts of one error. The numbers are explained below.
  1. Stage. The first line says where pravo stopped. evaluating means both files are valid CUE and their values do not unify.
  2. Path. The text before the colon is the path of the field, counted from the top of the data. It is the path in the output, whatever way the files nest it.
  3. Message. The text after the path says what is wrong with the value. Here two values disagree.
  4. Locations. Each file:line:column is a place that the message is about. Open each one. The column is the start of the value.

pravo does not list every problem in a specification. It reports the first failing value and stops. Messages about that one value can arrive together. Fix it, run the command again, and the next one appears.

Remove the second file. The examples below use one file at a time.

terminal
$rm team.cue

The three stages

First line Where pravo stopped What to check
Error: loading .: It could not read the files as one package. Syntax, the package line, the file names.
Error: evaluating .: The files are valid. Their values do not unify. The path, the values and both locations.
Error: the value is not concrete: The flag -c found a value that is not final. The constraint that the message names.

The . is the directory. When you run pravo -C DIR eval, it is DIR.

Errors in loading

no package name

A file that does not start with a package line cannot join the estate.

estate.cuerejected
buckets: logs: name: "logs"
terminalexit 6
$pravo eval
Error: loading .:
build constraints exclude all CUE files in .:
    ./estate.cue: no package name

The message names the file. There is no line, because the problem is the whole file. Add package estate as the first line. When another file in the directory has a package line, the message is x.cue has no package clause; the other files are package estate. A4 shows that case.

missing ',' in struct literal

Fields on one line need a comma between them. On separate lines they do not.

estate.cuerejected
package estate

buckets: logs: {name: "logs" encrypted: true}
rules: ssh: port: 22
terminalexit 6
$pravo eval
Error: loading .:
missing ',' in struct literal:
    ./estate.cue:3:30
expected '}', found 'EOF':
    ./estate.cue:4:22

The first message locates the problem. Column 30 is where encrypted starts, the field that follows the missing comma. The second message, expected '}', is a side effect. The parser reached the end of the file while it still read the struct. Fix the first message and the second disappears.

found packages

Two files in one directory that start with different package lines cannot form one package.

estate.cue
package estate

buckets: logs: name: "logs"
prod.cuerejected
package prod

buckets: logs: encrypted: true
terminalexit 6
$pravo eval
Error: loading .:
prod.cue is package prod; the other files are package estate

The message names the file and the package of the other files. Give every file the same package line. This page removes the second file instead.

terminal
$rm prod.cue

Errors in evaluation

reference "platform" not found

A word without quotes is a name. When no field has that name, CUE cannot find it.

estate.cuerejected
package estate

buckets: logs: tags: owner: platform
terminalexit 6
$pravo eval
Error: evaluating .:
buckets.logs.tags.owner: reference "platform" not found:
    ./estate.cue:3:29

The column is the first letter of the word. Quote the string. A1 explains the rule.

structural cycle

A word that names a field above it points back into itself.

estate.cuerejected
package estate

buckets: logs: name: logs
terminalexit 6
$pravo eval
Error: evaluating .:
buckets.logs.name: structural cycle

logs is the name of the field that contains name. CUE cannot resolve a field in terms of itself. This message has no location. Look at the field in the path and quote the string.

conflicting values, with two types

When the two values differ in type, the message adds the reason in brackets.

estate.cueconflict
package estate

size: 3
size: "3"
terminalexit 6
$pravo eval
Error: evaluating .:
size: conflicting values 3 and "3" (mismatched types int and string):
    ./estate.cue:3:7
    ./estate.cue:4:7

mismatched types int and string is the reason. A number and a string never unify. A3 covers conflicts.

invalid value, out of bound

A value outside a bound names the bound.

estate.cuerejected
package estate

port: int & >=1 & <=65535
port: 70000
terminalexit 6
$pravo eval
Error: evaluating .:
port: invalid value 70000 (out of bound <=65535):
    ./estate.cue:3:19
    ./estate.cue:4:7

The first location is the bound that rejected the value, and the second is the value. A5 covers bounds.

An error from -c

incomplete value

The flag -c fails while any value is still a constraint.

estate.cuevalid
package estate

buckets: logs: retention_days: int
terminalrejectedexit 1
$pravo eval -c
Error: the value is not concrete:
buckets.logs.retention_days: incomplete value int:
    ./estate.cue:3:32

The message names the constraint that is left. A2 covers concrete values, and Why is my value incomplete? covers the causes.

The lessons that follow add three messages. A6 has empty disjunction, when a value matches none of the choices. A8 has field not allowed, when a name is not declared. A11 has reference "bse" not found, the same message as above for a misspelt name.

Predict

The next file has three mistakes.

estate.cuerejected
package estate

buckets: logs: {name: "logs" encrypted: true}
buckets: logs: tags: owner: platform

rules: ssh: port: 22
rules: ssh: port: 220

Decide before you open the answer.

Predict How many of the three mistakes does one run of pravo report?

One. The missing comma stops pravo while it loads the file, before it evaluates any value. The second message is a side effect of the comma, as in the entry above. The other two mistakes are not reached yet.

terminalexit 6
$pravo eval
Error: loading .:
missing ',' in struct literal:
    ./estate.cue:3:30
expected '}', found 'EOF':
    ./estate.cue:7:23

Exercise

Exercise

Fix three mistakes, one error at a time

estate.cue holds the file above. Run pravo eval, read the first error, fix that line and run again. Repeat until the command prints the data. The ssh port is 22.

check.sh
want() { [ "$(pravo eval -e "$1" 2>/dev/null)" = "$2" ] || { echo "$1 should be $2"; exit 1; }; }
want buckets.logs.name '"logs"'
want buckets.logs.encrypted true
want buckets.logs.tags.owner '"platform"'
want rules.ssh.port 22
echo ok

Run the check on the start state. It fails.

terminalexit 1
$sh check.sh
buckets.logs.name should be "logs"
Hint 1

Fix them in the order pravo reports them: a comma, a pair of quotes, one port number.

Hint 2

The comma is in missing ',' in struct literal, the quotes in reference "platform" not found. The port is a conflict, covered in A3.

Solution
estate.cue
package estate

buckets: logs: {name: "logs", encrypted: true}
buckets: logs: tags: owner: "platform"

rules: ssh: port: 22

Recap

  • An error has four parts: the stage, the path, the message and the locations. Open each location.
  • loading means the files are not one package. evaluating means the values do not unify. not concrete means -c found a constraint.
  • pravo reports the first failing value. Fix it and run again.

Check yourself

An error starts with Error: loading .:. Did pravo evaluate any value?

No. It stopped while it read the files: a syntax error, a missing package line or two package names.

What does the first location of invalid value 70000 (out of bound <=65535) point to?

The bound that rejected the value. The second location is the value.

Go back to A4 to continue the track.