d2lang/d2 · error
%v
Error message
%v
What it means
When the worker reply channel closes, runWorkers checks errhrefs for image URLs that failed to fetch. If any failed, it returns them joined as a single error via fmt.Errorf("%v", errhrefs); the caller cannot use errors.Is/As on it because it's a stringified list, not a wrapped error.
Source
Thrown at lib/imgbundler/imgbundler.go:152
to: bundledImage,
}:
}
}()
}
}()
t := time.NewTicker(time.Second * 5)
defer t.Stop()
for {
select {
case <-ctx.Done():
return svg, fmt.Errorf("failed to wait for workers: %w", ctx.Err())
case <-t.C:
l.Info("fetching images...")
case repl, ok := <-replc:
if !ok {
if len(errhrefs) > 0 {
return svg, fmt.Errorf("%v", errhrefs)
}
return svg, nil
}
svg = bytes.Replace(svg, repl.from, repl.to, -1)
}
}
}
func worker(ctx context.Context, l simplelog.Logger, inputPath string, href []byte, isRemote, cacheImages bool) ([]byte, error) {
if cacheImages {
if hit, ok := imgCache.Load(string(href)); ok {
return hit.([]byte), nil
}
}
var buf []byte
var mimeType string
var err error
if isRemote {View on GitHub (pinned to 0d69dca6f5)
Solutions
- Fix or remove the failing image URLs listed in the error output
- Host images locally or inline them as data: URIs
- Verify network access to those hosts (proxy config, firewall)
- Download and reference the images via local paths to avoid remote fetch entirely
Example fix
// before (in diagram) icon: https://internal-wiki.company/logo.svg // 404 // after icon: https://cdn.company.com/public/logo.svg // reachable, or data:image/svg+xml;base64,...
Defensive patterns
Strategy: try-catch
Validate before calling
urls := extractImageHrefs(svg)
for _, u := range urls {
resp, err := http.Head(u)
if err != nil || resp.StatusCode >= 400 {
return fmt.Errorf("image %s not fetchable (status %v)", u, statusCodeOr(err))
}
} Try / catch
svg, err := imgbundler.Bundle(ctx, svgBytes)
if err != nil {
// err is a stringified list of failed hrefs — parse it for reporting
if strings.Contains(err.Error(), "http") {
log.Printf("some images failed; consider inlining them: %v", err)
}
return err
} Prevention
- Pre-validate every image URL with a HEAD request before bundling
- Prefer local paths or data: URIs over remote hotlinks
- Avoid URLs behind auth, expiring tokens, or bot-blocked CDNs
- Treat this error's text as a URL list: split and report each failing href
When it happens
Trigger: One or more remote image hrefs in the SVG failed to download (HTTP error, DNS failure, unsupported scheme), workers finish, channel closes, and errhrefs is non-empty.
Common situations: Diagrams referencing private/expired image URLs, hotlinks blocked by CDNs, offline environments, or URLs requiring auth/cookies.
Related errors
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/1f6f205ff46c61fe.
Report an issue: GitHub.