evanw/esbuild · error

could not decode base64 data: %s

Error message

could not decode base64 data: %s

What it means

Returned by DataURL.DecodeData when a `data:` URL marked as base64 (`;base64` suffix) contains bytes that fail Go's base64.StdEncoding.DecodeString. esbuild encounters data URLs during import/URL resolution (e.g. `import x from 'data:text/javascript;base64,...'`). This indicates the data URL is malformed at the byte level, not just unsupported.

Source

Thrown at internal/resolver/dataurl.go:65

	// Hard-code a few supported types
	switch mimeType {
	case "text/css":
		return MIMETypeTextCSS
	case "text/javascript":
		return MIMETypeTextJavaScript
	case "application/json":
		return MIMETypeApplicationJSON
	default:
		return MIMETypeUnsupported
	}
}

func (parsed DataURL) DecodeData() (string, error) {
	// Try to read base64 data
	if parsed.isBase64 {
		bytes, err := base64.StdEncoding.DecodeString(parsed.data)
		if err != nil {
			return "", fmt.Errorf("could not decode base64 data: %s", err.Error())
		}
		return string(bytes), nil
	}

	// Try to read percent-escaped data
	content, err := url.PathUnescape(parsed.data)
	if err != nil {
		return "", fmt.Errorf("could not decode percent-escaped data: %s", err.Error())
	}
	return content, nil
}

View on GitHub (pinned to 6ff1d8b0d8)

Solutions

  1. Re-encode the payload with standard base64 padding (alphabet A-Za-z0-9+/).
  2. If the data is URL-safe base64, convert it to standard base64 or drop the ';base64' marker and percent-escape instead.
  3. Validate the data URL with a one-liner (e.g. Buffer.from(payload, 'base64')) before feeding it to esbuild.
  4. If the asset is large, prefer a file import with a loader (LoaderFile/LoaderBase64) instead of an inline data URL.

Example fix

// before
import x from 'data:text/javascript;base64,YWxlcnQoMQ==' // but with a stray char

// after
import x from 'data:text/javascript;base64,YWxlcnQoMSk='  // valid standard base64
Defensive patterns

Strategy: validation

Validate before calling

// Verify a base64 data URL payload decodes before feeding it to esbuild.
function checkBase64DataUrl(url) {
  if (!url.startsWith('data:') || !url.includes(';base64,')) return true
  const payload = url.slice(url.indexOf(',') + 1)
  try { Buffer.from(payload, 'base64') } catch { return false }
  return true
}
if (!checkBase64DataUrl(specifier)) throw new Error('Malformed base64 data URL')

Type guard

function isStandardBase64(payload: string): boolean {
  return /^[A-Za-z0-9+/]*={0,2}$/.test(payload) && payload.length % 4 === 0
}

Try / catch

try {
  await esbuild.build({ ... })
} catch (e) {
  if (/could not decode base64 data/i.test(e.message)) {
    console.error('A data URL import has invalid base64:', e.message)
  }
  throw e
}

Prevention

When it happens

Trigger: An import specifier or CSS url(...) resolves to a data: URL whose payload after the comma is not valid standard base64: wrong length, non-alphabet characters, or a missing ';base64' marker mismatch. Reproduces when bundling source that embeds assets as data URLs.

Common situations: Hand-authored data URLs with typos; tools that emit URL-safe base64 ('-_' alphabet) into a standard-base64 slot; truncation of a data URL by a linter or templating engine; copy-paste that drops trailing '=' padding.

Related errors


AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03). Data as JSON: /data/errors/07da6443429f40ca.json. Report an issue: GitHub.