d2lang/d2 · error

unsupported content encoding

Error message

unsupported content encoding %q

What it means

decodeContentEncoding supports only gzip, br (brotli), and deflate. Any other Content-Encoding value (or an unrecognized token) hits the default branch and returns this error. The bundler cannot decode the response body, so the image fetch fails.

Solutions

  1. Configure the origin/CDN to serve gzip, br, or deflate (or identity) for images — images rarely need zstd
  2. Strip Accept-Encoding for zstd in any client/transport config you control so the server falls back to a supported encoding
  3. If you control the library, add a case for the encoding (e.g. zstd) in decodeContentEncoding
  4. Work around by fetching the asset without compression (Accept-Encoding: identity)

Example fix

// before
req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")
// after
req.Header.Set("Accept-Encoding", "gzip, deflate, br")
Defensive patterns

Strategy: validation

Validate before calling

allowed := map[string]bool{"gzip": true, "br": true, "deflate": true, "": true}
req.Header.Set("Accept-Encoding", "gzip, deflate, br") // never advertise zstd/compress

Try / catch

if _, _, err := httpGet(ctx, client, href); err != nil {
	if strings.Contains(err.Error(), "unsupported content encoding") {
		// refetch with Accept-Encoding: identity
	}
}

Prevention

When it happens

Trigger: Server advertises an encoding outside the supported set — e.g. zstd, compress, or a nonstandard token like 'x-gzip' — in the Content-Encoding header of an image response.

Common situations: Modern origins negotiating zstd (supported by browsers but not this client), proxies injecting 'compress', or misconfigured servers emitting unusual encoding tokens.

Related errors


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

Appendix: source

Thrown at lib/imgbundler/imgbundler.go:270

func decodeContentEncoding(buf []byte, contentEncoding string) ([]byte, error) {
	encodings := strings.Split(contentEncoding, ",")
	for i := len(encodings) - 1; i >= 0; i-- {
		encoding := strings.TrimSpace(strings.ToLower(encodings[i]))
		if encoding == "" || encoding == "identity" {
			continue
		}

		var err error
		switch encoding {
		case "gzip", "x-gzip":
			buf, err = gunzip(buf)
		case "br":
			buf, err = readDecoded(brotli.NewReader(bytes.NewReader(buf)))
		case "deflate":
			buf, err = inflate(buf)
		default:
			return nil, fmt.Errorf("unsupported content encoding %q", encoding)
		}
		if err != nil {
			return nil, err
		}
	}
	return buf, nil
}

func gunzip(buf []byte) ([]byte, error) {
	r, err := gzip.NewReader(bytes.NewReader(buf))
	if err != nil {
		return nil, err
	}
	defer r.Close()
	return readDecoded(r)
}

func inflate(buf []byte) ([]byte, error) {

View on GitHub (pinned to 0d69dca6f5)