Readable browser errors.
Playwright reports a failure as a wall of text: a Java
Error { message='…' name='…' stack='…' } envelope, the SAME text again
for every level of the cause chain, and a stack whose frames all point
inside the bundled driver (coreBundle.js, UtilityScript, async
dispatcher frames). The one line the caller needs — ReferenceError: foo is not defined — is buried in the middle of ~40 useless ones.
concise collapses that dump into:
<the real message> at <expression>:1:32 ; user frames only, capped
1 | document.querySelector('#nope').getBoundingClientRect()
| ^^^^^^^^^^^^^^^^^^^^^^^
Call log: ; kept — it says what the driver awaited - waiting for locator('#x')
The numbered excerpt with the caret run is the :source code frame: pass
the code you sent to the browser ({:source script}) and the reported
position is pointed at, babashka-style. JS positions come from the
at <expression>:line:col frame and are resolved against the TRIMMED
source, because Playwright trims an expression before evaluating it; a
caller that already knows the position (SCI's :line/:column ex-data)
passes it explicitly and the source is used as given.
Pure string→string (no Throwable, no IO), so the daemon, the CLI and
library callers all format errors the same way. It never throws — any
internal failure falls back to the trimmed original. What it never does is
invent or drop information the caller cannot recover: the untouched
original is written to the session log (spel logs).
Readable browser errors.
Playwright reports a failure as a wall of text: a Java
`Error { message='…' name='…' stack='…' }` envelope, the SAME text again
for every level of the cause chain, and a stack whose frames all point
inside the bundled driver (`coreBundle.js`, `UtilityScript`, `async`
dispatcher frames). The one line the caller needs — `ReferenceError: foo
is not defined` — is buried in the middle of ~40 useless ones.
`concise` collapses that dump into:
<the real message>
at <expression>:1:32 ; user frames only, capped
1 | document.querySelector('#nope').getBoundingClientRect()
| ^^^^^^^^^^^^^^^^^^^^^^^
Call log: ; kept — it says what the driver awaited
- waiting for locator('#x')
The numbered excerpt with the caret run is the `:source` code frame: pass
the code you sent to the browser (`{:source script}`) and the reported
position is pointed at, babashka-style. JS positions come from the
`at <expression>:line:col` frame and are resolved against the TRIMMED
source, because Playwright trims an expression before evaluating it; a
caller that already knows the position (SCI's `:line`/`:column` ex-data)
passes it explicitly and the source is used as given.
Pure string→string (no `Throwable`, no IO), so the daemon, the CLI and
library callers all format errors the same way. It never throws — any
internal failure falls back to the trimmed original. What it never does is
invent or drop information the caller cannot recover: the untouched
original is written to the session log (`spel logs`).(concise msg)(concise msg opts)Collapses a raw Playwright/Java error message into the short, readable form described in this namespace's docstring.
Params:
msg - raw error text (may be nil, multi-line, or a →-joined chain).
opts - optional map:
:source - the code that was evaluated; enables the numbered excerpt
with the caret under the failing position.
:lang - :js or :clj, the language of :source. A :clj source
ignores JS at <expression> frames (they address the JS
string a Clojure form passed on, not the form).
:line - 1-based line into :source, when the caller already knows it
(SCI puts it in ex-data). Without it the position is read from
the at <expression>:line:col frame.
:column - 1-based column, paired with :line.
Returns:
The cleaned message, or nil when msg is nil or blank. Never returns a
blank string, never throws: on any internal failure the trimmed original
is returned.
Collapses a raw Playwright/Java error message into the short, readable
form described in this namespace's docstring.
Params:
`msg` - raw error text (may be nil, multi-line, or a `→`-joined chain).
`opts` - optional map:
`:source` - the code that was evaluated; enables the numbered excerpt
with the caret under the failing position.
`:lang` - `:js` or `:clj`, the language of `:source`. A `:clj` source
ignores JS `at <expression>` frames (they address the JS
string a Clojure form passed on, not the form).
`:line` - 1-based line into `:source`, when the caller already knows it
(SCI puts it in ex-data). Without it the position is read from
the `at <expression>:line:col` frame.
`:column` - 1-based column, paired with `:line`.
Returns:
The cleaned message, or nil when `msg` is nil or blank. Never returns a
blank string, never throws: on any internal failure the trimmed original
is returned.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |