Skip to content

resvg/usvg render warnings are discarded: no log implementation is installed #78

Description

@llimllib

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions