gohugoio/hugo · error
failed to resolve media type for remote resource
Error message
failed to resolve media type for remote resource %q
What it means
Returned by `Client.FromRemote` (remote.go:347-350) when, after exhausting every resolution path -- `Content-Type` header lookup in configured MediaTypes, `media.FromString`, file-extension hints, and content-based detection via `media.FromContent` -- the media type is still zero. Hugo refuses to create a Resource without a known media type because downstream pipelines (target path, suffix, transforms) all depend on it.
Solutions
- Add the `Content-Type` server-side, or have the endpoint return one.
- Provide a URL with a clear file extension (e.g. append `?format=json` is not enough -- use a real path component).
- Allow the relevant media type in `security.http.mediaTypes` config.
- If the body is real but untyped, save it locally and create the resource with `resources.FromString`/`resources.Get` plus explicit `MediaType`.
- Confirm the response is non-empty (an empty 200 body defeats content sniffing).
Example fix
// hugo.toml -- before [security.http.mediaTypes] allowed = [] // after [security.http.mediaTypes] allowed = ["application/json"]
Defensive patterns
Strategy: validation
Validate before calling
// Probe Content-Type before relying on the resource.
import (
"net/http"
)
func probeContentType(url string) (string, error) {
resp, err := http.Head(url)
if err != nil { return "", err }
return resp.Header.Get("Content-Type"), nil
} Try / catch
// Fallback: fetch bytes, write locally, create typed resource.
if r, err := resources.GetRemote(url); err != nil {
if strings.Contains(err.Error(), "failed to resolve media type") {
body := fetchBytes(url)
return resources.FromString("fetched.bin", string(body)), nil
}
} Prevention
- Ensure endpoints send `Content-Type`.
- Whitelist needed types under `security.http.mediaTypes`.
- Use URLs with explicit file extensions for untyped endpoints.
When it happens
Trigger: Remote response has no `Content-Type` header, the URL has no recognizable file extension, and the body content is ambiguous or empty (so `media.FromContent` cannot classify). Also when the `Content-Type` is set but not in the allowed `security.http.mediaTypes` set and content sniffing also fails.
Common situations: Fetching JSON from an endpoint that returns no Content-Type and a body shorter than sniff thresholds; fetching binary blobs with generic `application/octet-stream` excluded by security policy; fetching from a server that returns 200 with empty body; misconfigured `mediaTypes` in hugo.toml so a valid type string isn't recognized; CDN stripping Content-Type.
Related errors
- failed to decode options for resource
- invalid timeout for resource
- failed to compile whitelist pattern
- failed to create request for resource
- failed to create resource spec
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/056d5d92ef7ed245.
Report an issue: GitHub.
Appendix: 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 52c9bd7908)