Summary
resvg/usvg emit log diagnostics when they cannot render part of an SVG, but mdriver
installs no log implementation. Every one of those messages is discarded, so SVG and
Mermaid rendering problems are invisible: mdriver emits a technically-valid image with
missing content and reports nothing.
This was the third "why wasn't this caught" gap noted in #74. That issue framed it as
"resvg fails silently", which isn't quite right — resvg is not silent, we are simply not
listening.
Evidence
usvg 0.48.1 has ~60 log::warn! call sites for content it skips. The one relevant to
#74 is usvg-0.48.1/src/text/mod.rs:143:
let id = fontdb.query(&query);
if id.is_none() {
log::warn!(
"No match for '{}' font-family.",
font.families.iter().map(|f| f.to_string()).collect::<Vec<_>>().join(", ")
);
}
Others cover cases that would each produce a silently-degraded image, e.g.:
| location |
message |
text/mod.rs:197 |
Fallback from {} to {}. |
parser/image.rs:93 |
Failed to load '{}'. Skipped. |
parser/image.rs:105 |
'{}' is not a PNG, JPEG, GIF, WebP or SVG(Z) image. |
tree/mod.rs:1492 |
Image has an invalid size. Skipped. |
parser/filter.rs:359 |
'{}' is not a valid filter primitive. Skipped. |
text/flatten.rs:377 |
Failed to find SVG glyph node for glyph {} |
Confirming nothing reaches stderr today:
$ printf '```mermaid\nflowchart LR\n A[Client] --> B(Gateway)\n```\n' \
| mdriver --color=always --images kitty 2>/tmp/err.txt >/dev/null
$ wc -c < /tmp/err.txt
0
And that a logger does surface it — minimal reproduction against the same resvg version,
rendering <text font-family="definitely-missing-font-xyz"> with that family absent:
[WARN] No match for '"definitely-missing-font-xyz"' font-family.
(render completed)
The render "succeeds" and returns a tree; only the text is gone.
Why it matters
The failure mode is bad: output looks plausible. In #74, Mermaid flowcharts rendered
shapes with every label dropped, and no layer raised an error. A visible warning would
have made that a five-minute diagnosis instead of a pixel-counting investigation.
Suggested approach
Add log as a dependency and install a minimal logger that writes to stderr. Points worth
deciding:
- Default level. Some usvg warnings are noisy and benign (
Fallback from X to Y.
fires routinely for emoji). Defaulting to silent and enabling via a flag —
--verbose, or honoring RUST_LOG — is probably better than warning by default.
- Don't corrupt output. Diagnostics must go to stderr only; stdout carries the
terminal image payload and ANSI stream.
- Keep it small. A hand-rolled
log::Log impl is a few lines; env_logger pulls in
a regex-based filter, which is heavier than needed here.
- Streaming. mdriver renders Mermaid on a worker thread with a timeout
(try_render_mermaid), so a logger must be thread-safe. log's global logger already
is.
Notes
Not a bug in resvg/usvg — the diagnostics exist and the behavior of skipping unresolvable
content matches CSS font-matching rules. This is purely mdriver not consuming them.
Related: #74 (mermaid text dropped; the concrete case this would have surfaced).
Summary
resvg/usvgemitlogdiagnostics when they cannot render part of an SVG, but mdriverinstalls no
logimplementation. Every one of those messages is discarded, so SVG andMermaid rendering problems are invisible: mdriver emits a technically-valid image with
missing content and reports nothing.
This was the third "why wasn't this caught" gap noted in #74. That issue framed it as
"resvg fails silently", which isn't quite right — resvg is not silent, we are simply not
listening.
Evidence
usvg0.48.1 has ~60log::warn!call sites for content it skips. The one relevant to#74 is
usvg-0.48.1/src/text/mod.rs:143:Others cover cases that would each produce a silently-degraded image, e.g.:
text/mod.rs:197Fallback from {} to {}.parser/image.rs:93Failed to load '{}'. Skipped.parser/image.rs:105'{}' is not a PNG, JPEG, GIF, WebP or SVG(Z) image.tree/mod.rs:1492Image has an invalid size. Skipped.parser/filter.rs:359'{}' is not a valid filter primitive. Skipped.text/flatten.rs:377Failed to find SVG glyph node for glyph {}Confirming nothing reaches stderr today:
And that a logger does surface it — minimal reproduction against the same resvg version,
rendering
<text font-family="definitely-missing-font-xyz">with that family absent:The render "succeeds" and returns a tree; only the text is gone.
Why it matters
The failure mode is bad: output looks plausible. In #74, Mermaid flowcharts rendered
shapes with every label dropped, and no layer raised an error. A visible warning would
have made that a five-minute diagnosis instead of a pixel-counting investigation.
Suggested approach
Add
logas a dependency and install a minimal logger that writes to stderr. Points worthdeciding:
Fallback from X to Y.fires routinely for emoji). Defaulting to silent and enabling via a flag —
--verbose, or honoringRUST_LOG— is probably better than warning by default.terminal image payload and ANSI stream.
log::Logimpl is a few lines;env_loggerpulls ina regex-based filter, which is heavier than needed here.
(
try_render_mermaid), so a logger must be thread-safe.log's global logger alreadyis.
Notes
Not a bug in resvg/usvg — the diagnostics exist and the behavior of skipping unresolvable
content matches CSS font-matching rules. This is purely mdriver not consuming them.
Related: #74 (mermaid text dropped; the concrete case this would have surfaced).