gohugoio/hugo · error
failed to resolve media type for remote resource %q
Error message
failed to resolve media type for remote resource %q
What it means
After fetching, Hugo must assign a media type to the remote resource so it can be processed and given a file suffix. It tries, in order: the Content-Type header (if configured/accepted), extensions derived from the content type, the URL path's file extension, and finally content sniffing via `media.FromContent`. If all of these yield nothing — typically a missing/garbage Content-Type, an extension-less URL, and unrecognizable bytes — Hugo cannot proceed and fails with this error. For HEAD requests there is no body to sniff, making this stricter.
Source
Thrown at resources/resource_factories/create/remote.go:349
if exts != nil {
extensionHints = exts
}
}
// Look for a file extension. If it's .txt, look for a more specific.
if extensionHints == nil || extensionHints[0] == ".txt" {
if ext := path.Ext(filename); ext != "" {
extensionHints = []string{ext}
}
}
// Now resolve the media type primarily using the content.
mediaType = media.FromContent(c.rs.MediaTypes(), extensionHints, body)
}
if mediaType.IsZero() {
return nil, fmt.Errorf("failed to resolve media type for remote resource %q", uri)
}
userKey = filename[:len(filename)-len(path.Ext(filename))] + "_" + userKey + mediaType.FirstSuffix.FullSuffix
data := responseToData(res, false, options.ResponseHeaders)
return c.rs.NewResource(
resources.ResourceSourceDescriptor{
MediaType: mediaType,
Data: data,
GroupIdentity: identity.StringIdentity(optionsKey),
LazyPublish: true,
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
return hugio.NewReadSeekerNoOpCloser(bytes.NewReader(body)), nil
},
TargetPath: userKey,
})
})
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Make the server send a correct `Content-Type` header, or use a URL variant that ends in a real file extension so Hugo can infer from the path.
- Add the server's content type to your site config under `mediaTypes` (with a suffix) so `GetByType` resolves it.
- If security config filters accepted types, review `security.http.mediaTypes` to ensure the returned Content-Type is allowed.
- Avoid HEAD for such endpoints — use GET so content sniffing can run on the body.
Example fix
# config: teach Hugo the server's content type # before: (no mediaTypes entry, server sends application/vnd.foo) # after (hugo.toml) [mediaTypes.'application/vnd.foo'] suffixes = ['foo']
Defensive patterns
Strategy: validation
Validate before calling
{{/* give Hugo something to resolve the type from: extension or explicit mediaType */}}
{{ $r := resources.GetRemote "https://api.example.com/render?id=42" (dict "headers" (dict "Accept" "image/png")) }}
{{/* or force it: */}}
{{ $r := resources.GetRemote $url | resources.Copy "images/chart.png" }} Prevention
- Prefer URLs whose path ends in a real file extension; extensionless API endpoints commonly trigger this
- If the server returns a generic or missing Content-Type, use resources.Copy to a name with the correct extension so the type is derivable
- For truly custom formats, register the media type/suffix in site config (mediaTypes) before fetching
- Check the endpoint's Content-Type header with curl -I when diagnosing — the server may send application/octet-stream
When it happens
Trigger: `resources.GetRemote` against endpoints returning no or bogus `Content-Type` (e.g. `application/octet-stream` for an unknown format) on URLs without a file extension (API routes like `/download?id=123`), HEAD-method requests where the header is the only signal and it maps to no known media type, or content types not present in Hugo's `mediaTypes` configuration and unsniffable content.
Common situations: Download endpoints and signed URLs (S3 presigned links) that omit extensions and serve `octet-stream`, custom or vendor MIME types (`application/vnd.*`) not in Hugo's media type table, and servers misconfigured to send empty Content-Type headers.
Related errors
- MIME %q not supported
- MIME %q not supported
- must provide an URL and optionally an options map
- resources in Concat must be of the same Media Type, got %q a
- failed to parse URL for resource %s: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/056d5d92ef7ed245.json.
Report an issue: GitHub ↗.