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
- Re-encode the payload with standard base64 padding (alphabet A-Za-z0-9+/).
- If the data is URL-safe base64, convert it to standard base64 or drop the ';base64' marker and percent-escape instead.
- Validate the data URL with a one-liner (e.g. Buffer.from(payload, 'base64')) before feeding it to esbuild.
- 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
- Generate data URLs from bytes via Buffer.from(x).toString('base64'), not by hand.
- Prefer file-based loaders (loader: 'file' | 'base64') over inline data URLs for assets.
- Lint import specifiers matching /^data:.*;base64,/ in a pre-build step.
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.