d2lang/d2 · error

failed to compile %s: %w

Error message

failed to compile %s: %w

What it means

Run wraps any error returned by compile() as 'failed to compile <inputPath>: %w' when no partial output was written. The inner error is the real cause (parse error, layout failure, render failure, etc.).

Source

Thrown at d2cli/main.go:420

		}
		boardPath = key.StringIDA()
	}

	ctx, cancel := timelib.WithTimeout(ctx, time.Minute*2)
	defer cancel()

	animateInterval := *animateIntervalFlag
	if outputFormat == GIF && animateInterval == 0 {
		animateInterval = 1000
		ms.Log.Debug.Printf("GIF export: animate-interval not specified, defaulting to 1000ms")
	}

	_, written, err := compile(ctx, ms, plugins, nil, layoutFlag, renderOpts, fontFamily, monoFontFamily, animateInterval, inputPath, outputPath, boardPath, noChildren, *bundleFlag, *forceAppendixFlag, pw.Browser, outputFormat, *asciiModeFlag)
	if err != nil {
		if written {
			return fmt.Errorf("failed to fully compile (partial render written) %s: %w", ms.HumanPath(inputPath), err)
		}
		return fmt.Errorf("failed to compile %s: %w", ms.HumanPath(inputPath), err)
	}
	return nil
}

func LayoutResolver(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin) func(engine string) (d2graph.LayoutGraph, error) {
	cached := make(map[string]d2graph.LayoutGraph)
	return func(engine string) (d2graph.LayoutGraph, error) {
		if c, ok := cached[engine]; ok {
			return c, nil
		}

		plugin, err := d2plugin.FindPlugin(ctx, plugins, engine)
		if err != nil {
			if errors.Is(err, exec.ErrNotFound) {
				return nil, layoutNotFound(ctx, plugins, engine)
			}
			return nil, err
		}

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Inspect the wrapped inner error for the exact failing stage
  2. Validate the .d2 input compiles (fix syntax or unknown keywords)
  3. Check the --layout engine name matches an available plugin

Example fix

// before
d2 --layout bogus input.d2 out.svg  // failed to compile input.d2: ...
// after
d2 --layout elk input.d2 out.svg
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := os.Stat(inputPath); err != nil {
    return fmt.Errorf("input missing: %w", err)
}

Try / catch

if err := d2cli.Run(...); err != nil {
    if cause := errors.Unwrap(err); cause != nil {
        log.Printf("compile failed for %s: %v", inputPath, cause)
    }
}

Prevention

When it happens

Trigger: Any failure inside compile() before output was written: D2 syntax errors, unknown layout engine, render/export failures on the given input.

Common situations: Invalid D2 script, misconfigured layout key, browser/playwright issues when rendering PNG, or missing fonts.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/b8836094ee5824c2. Report an issue: GitHub.