Check out v4 of the Fauna CLI
v4 of the Fauna CLI is now GA. The new version introduces enhancements to the developer experience, including an improved authentication workflow. To get started, check out the CLI v4 quick start. Migrating from v3 of the CLI? See the CLI migration guide. |
Query summary
Responses from the Fauna Core HTTP API’s
Query endpoint
include a summary
property containing a JSON-escaped string.
The summary
contains a human-readable description of errors, warnings,
or custom messages returned by the query. If an error or warning,
the summary
includes the location of the issue and a hint for
resolving it, if applicable.
summary
can contain multiple messages, which are separated using a newline.
Error summaries
Error responses include a summary
that describes the issue causing the error.
For example, the following FQL query attempts to create and call a collection in the same query:
Collection.create({name: "Foo"})
Collection("Foo").create({ bar: "baz"})
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H "Authorization: Bearer $FAUNA_SECRET" \
-H 'Content-Type: application/json' \
-H 'X-Format: tagged' \
-d '{
"query": "Collection.create({name: \"Foo\"})\n\nCollection(\"Foo\").create({ bar: \"baz\"})"
}'
Response:
{
"error": {
"code": "invalid_argument",
"message": "invalid argument `collection`: No such user collection `Foo`."
},
"summary": "error: invalid argument `collection`: No such user collection `Foo`.\nat *query*:3:11\n |\n3 | Collection(\"Foo\").create({ bar: \"baz\"})\n | ^^^^^^^\n |\nhint: A collection cannot be created and used in the same query.\n |\n3 | Collection(\"Foo\").create({ bar: \"baz\"})\n | ^^^^^^^\n |",
...
}
When unescaped, the response’s summary
renders as:
error: invalid argument `collection`: No such user collection `Foo`.
at *query*:3:11
|
3 | Collection("Foo").create({ bar: "baz"})
| ^^^^^^^
|
hint: A collection cannot be created and used in the same query.
|
3 | Collection("Foo").create({ bar: "baz"})
| ^^^^^^^
|
Abort error summaries
Abort errors include a query
stack trace in the response’s
summary
field. The stack
trace includes the lines that triggered the error.
For example, the following FQL query includes an
abort()
call:
Customer.all()
abort("Discard")
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H "Authorization: Bearer $FAUNA_SECRET" \
-H 'Content-Type: application/json' \
-H 'X-Format: tagged' \
-d '{
"query": "Customer.all()\nabort(\"Discard\")"
}'
Response:
{
"error": {
"code": "abort",
"message": "Query aborted.",
"abort": "Discard"
},
"summary": "error: Query aborted.\nat *query*:2:6\n |\n2 | abort(\"Discard\")\n | ^^^^^^^^^^^\n |",
...
}
When unescaped, the response’s summary
renders as:
error: Query aborted.
at *query*:2:6
|
2 | abort("Discard")
| ^^^^^^^^^^^
|
Query stack traces for UDF calls
When calling a user-defined
function (UDF) that uses abort()
, the
summary’s query stack trace includes both query and UDF lines if the
authentication secret has the
built-in admin
or
server
role.
For example, the following response’s summary
field contains a query stack
trace with both query and UDF lines:
{
"error": {
"code": "abort",
"message": "Query aborted.",
"abort": "Can not call checkout with status other than processing."
},
"summary": "error: Query aborted.\nat *udf:checkout*:6:10\n |\n6 | abort(\"Can not call checkout with status other than processing.\")\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\nat *query*:1:9\n |\n1 | checkout(420701723228635213, \"cart\", {})\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n\ninfo at *udf:checkout*:3: log - test123\n\ninfo: \"debug - test123\"\nat *udf:checkout*:4:6\n |\n4 | dbg(\"debug - test123\")\n | ^^^^^^^^^^^^^^^^^^^\n |",
...
}
When unescaped, the response’s summary
renders as:
error: Query aborted.
at *udf:checkout*:6:10
|
6 | abort("Can not call checkout with status other than processing.")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
at *query*:1:9
|
1 | checkout(420701723228635213, "cart", {})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
info at *udf:checkout*:3: log - test123
info: "debug - test123"
at *udf:checkout*:4:6
|
4 | dbg("debug - test123")
| ^^^^^^^^^^^^^^^^^^^
|
For secrets with the built-in
server-readonly
role or a
user-defined role, the
summary’s stack trace only includes query lines, not UDF lines. This applies
even if the UDF is annotated with
@role(admin)
or
@role(server)
.
This prevents unprivileged users from inferring sensitive UDF logic or data.
For example, the previous response’s summary
field contains a query stack
trace with only query lines:
{
"error": {
"code": "abort",
"message": "Query aborted.",
"abort": "Can not call checkout with status other than processing."
},
"summary": "error: Query aborted.\nat *query*:1:9\n |\n1 | checkout(420701723228635213, \"cart\", {})\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |",
...
}
When unescaped, the response’s summary
renders as:
error: Query aborted.
at *query*:1:9
|
1 | checkout(420701723228635213, "cart", {})
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
Warning summaries
If typechecking is enabled, queries that
include a built-in method but don’t call the method return a
warning in the summary
.
For example, the following FQL query omits the parentheses (()
) on a
Time.now()
call:
Time.now
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H 'Authorization: Bearer <FAUNA_SECRET>' \
-H 'Content-Type: application/json' \
-H 'X-Format: tagged' \
-d '{
"query": "Time.now"
}'
Response:
{
"data": "[function now()]",
"static_type": "() => Time",
"summary": "warning: Function is not called.\nat *query*:1:1\n |\n1 | Time.now\n | ^^^^^^^^\n |\nhint: Call the function.\n |\n1 | Time.now()\n | ++\n |",
...
}
When unescaped, the response’s summary
renders as:
warning: Function is not called.
at *query*:1:1
|
1 | Time.now
| ^^^^^^^^
|
hint: Call the function.
|
1 | Time.now()
| ++
|
Similarly, queries that include an anonymous function but don’t call the FQL
return a warning in the summary
.
For example, the following FQL query defines a function but doesn’t call it:
(x, y) => x + y
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H 'Authorization: Bearer <FAUNA_SECRET>' \
-H 'Content-Type: application/json' \
-H 'X-Format: tagged' \
-d '{
"query": "(x, y) => x + y"
}'
Response:
{
"data": "[function <lambda>]",
"static_type": "((Number, Number) => Number) & ((String, String) => String)",
"summary": "warning: Function is not called.\nat *query*:1:1\n |\n1 | (x, y) => x + y\n | ^^^^^^^^^^^^^^^\n |\nhint: Call the function.\n |\n1 | (x, y) => x + y()\n | ++\n |",
...
}
When unescaped, the response’s summary
renders as:
warning: Function is not called.
at *query*:1:1
|
1 | (x, y) => x + y
| ^^^^^^^^^^^^^^^
|
hint: Call the function.
|
1 | (x, y) => x + y()
| ++
|
Log and debug messages
Log messages
Use log()
to pass messages
to the summary
. The messages are annotated as info
.
log()
is similar to console.log()
or
print()
in other programming languages.
log()
supports
interpolated strings
containing FQL variables.
For example, the following FQL query logs several summary
messages:
log("Before assignment")
let x = 5
let y = { lat: 37.5542782, long: -122.3007394 }
log("After assignment x=#{x}")
log(y)
x
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H 'Authorization: Bearer <FAUNA_SECRET>' \
-H 'Content-Type: application/json' \
-H 'X-Format: tagged' \
-d '{
"query": "log(\"Before assignment\")\nlet x = 5\nlet y = { lat: 37.5542782, long: -122.3007394 }\nlog(\"After assignment x=#{x}\")\nlog(y)\nx\n"
}'
Unlike dbg()
,
log()
does not return a value. The message
is excluded from the query results in data
.
The summary
includes the query lines that called log()
:
{
"data": {
"@int": "5"
},
"static_type": "5",
"summary": "info at *query*:1: Before assignment\n\ninfo at *query*:4: After assignment x=5\n\ninfo at *query*:5: { lat: 37.5542782, long: -122.3007394 }",
...
}
When unescaped, the response’s summary
renders as:
info at *query*:1: Before assignment
info at *query*:4: After assignment x=5
info at *query*:5: { lat: 37.5542782, long: -122.3007394 }
Debug messages
You can use dbg()
inline within method calls
for debugging.
For example, the following FQL query uses
dbg()
within a
collection.create()
call:
let x = "key limes"
Product.create(
// `dbg()` outputs its message. In this case,
// it outputs an object containing the `name`
// and `stock` properties.
dbg({
name: "#{x}",
stock: 1 + 2 + 3,
})
)
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H 'Authorization: Bearer <FAUNA_SECRET>' \
-H 'Content-Type: application/json' \
-H 'X-Format: tagged' \
-d '{
"query": "let x = \"key limes\"\n\nProduct.create(\n dbg({\n name: \"#{x}\",\n stock: 1 + 2 + 3,\n })\n)"
}'
The message is included in the query results in data
. The summary
includes
the query lines that called dbg()
:
{
"data": {
"@doc": {
"id": "413921254218661965",
"coll": {
"@mod": "Product"
},
"ts": {
"@time": "2099-11-07T18:41:59.173Z"
},
"name": "key limes",
"stock": {
"@int": "6"
}
}
},
"static_type": "Product",
"summary": "info: { name: \"key limes\", stock: 6 }\nat *query*:4:6\n |\n4 | dbg({\n | ______^\n5 | | name: \"#{x}\",\n6 | | stock: 1 + 2 + 3,\n7 | | })\n | |____^\n |",
...
}
When unescaped, the response’s summary
renders as:
info: { name: "key limes", stock: 6 }
at *query*:4:6
|
4 | dbg({
| ______^
5 | | name: "#{x}",
6 | | stock: 1 + 2 + 3,
7 | | })
| |____^
|
Log and debug messages for UDF calls
When calling a user-defined
function (UDF) that uses log()
or
dbg()
, the visibility of the respective log
or debug messages depends on the
authentication secret's role:
Role | Visibility |
---|---|
Messages are returned in the response’s
|
|
Messages are not returned, even if the UDF is annotated with
|
Performance hints
If a query request’s X-Performance-Hints
header is true
, responses include
performance hints, if applicable, in
the summary
field.
The hints provide actionable steps for improving the query’s performance. You typically use performance hints when testing or prototyping FQL queries in the Fauna Dashboard Shell.
For example, Fauna emits performance hints for uncovered index queries. The following FQL query uses an index but projects fields that aren’t covered by the index definition:
// This is an uncovered query.
// `stock` is not one of the terms or values
// in the `sortedByPriceLowToHigh()` index definition.
Product.sortedByPriceLowToHigh() { name, stock }
The query as a Query endpoint request:
curl -X POST \
'https://db.fauna.com/query/1' \
-H "Authorization: Bearer $FAUNA_SECRET" \
-H 'Content-Type: application/json' \
-H 'X-Performance-Hints: true' \
-H 'X-Format: tagged' \
-d '{
"query": "Product.sortedByPriceLowToHigh() { name, stock }"
}'
Response:
{
...
"summary": "performance_hint: non_covered_document_read - .stock is not covered by the Product.sortedByPriceLowToHigh index. See https://docs.fauna.com/performance_hint/non_covered_document_read.\nat *query*:1:42\n |\n1 | Product.sortedByPriceLowToHigh() { name, stock }\n | ^^^^^\n |",
...
}
When unescaped, the response’s summary
renders as:
performance_hint: non_covered_document_read - .stock is not covered by the Product.sortedByPriceLowToHigh index. See https://docs.fauna.com/performance_hint/non_covered_document_read.
at *query*:1:42
|
1 | Product.sortedByPriceLowToHigh() { name, stock }
| ^^^^^
|
Query summaries in client drivers
Fauna’s client drivers include summary
values in a query info or query
response class. This class is used for both successful query responses and
errors:
-
JavaScript driver:
QueryInfo
-
Python driver:
QueryInfo
-
Go driver:
QueryInfo
-
.NET/C# driver:
QueryResponse
-
JVM driver:
QueryResponse
Is this article helpful?
Tell Fauna how the article can be improved:
Visit Fauna's forums
or email docs@fauna.com
Thank you for your feedback!