{"id":"d4e9508e97932612","repo":"gohugoio/hugo","slug":"cannot-parse-q-as-a-media-type","errorCode":null,"errorMessage":"cannot parse %q as a media type","messagePattern":"cannot parse %q as a media type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"media/mediaType.go","lineNumber":141,"sourceCode":"\tif err != nil {\n\t\treturn tp, err\n\t}\n\tfor i, e := range ext {\n\t\text[i] = strings.TrimPrefix(e, \".\")\n\t}\n\ttp.SuffixesCSV = strings.Join(ext, \",\")\n\ttp.Delimiter = DefaultDelimiter\n\ttp.init()\n\treturn tp, nil\n}\n\n// FromString creates a new Type given a type string on the form MainType/SubType and\n// an optional suffix, e.g. \"text/html\" or \"text/html+html\".\nfunc FromString(t string) (Type, error) {\n\tt = strings.ToLower(t)\n\tparts := strings.Split(t, \"/\")\n\tif len(parts) != 2 {\n\t\treturn Type{}, fmt.Errorf(\"cannot parse %q as a media type\", t)\n\t}\n\tmainType := parts[0]\n\tsubParts := strings.Split(parts[1], \"+\")\n\n\tsubType := strings.Split(subParts[0], \";\")[0]\n\n\tvar suffix string\n\n\tif len(subParts) > 1 {\n\t\tsuffix = subParts[1]\n\t}\n\n\tvar typ string\n\tif suffix != \"\" {\n\t\ttyp = mainType + \"/\" + subType + \"+\" + suffix\n\t} else {\n\t\ttyp = mainType + \"/\" + subType\n\t}","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/media/mediaType.go#L123-L159","documentation":"Hugo's media.FromString parses a MIME string of the form 'mainType/subType' with an optional '+suffix' (e.g. 'text/html', 'application/rss+xml'). It splits the input on '/' and requires exactly two parts; anything else is rejected with this error. It exists to catch malformed media type identifiers early, before they propagate into output-format and content-type resolution.","triggerScenarios":"Calling media.FromString / FromStringAndExt with a string that doesn't contain exactly one '/', e.g. 'html', 'text', 'text/html/extra', or an empty string. In practice this happens when Hugo decodes the site config's mediaTypes/outputFormats sections and a key isn't a valid 'type/subtype' string.","commonSituations":"A custom mediaTypes entry in hugo.toml/config.toml keyed by just the suffix (e.g. [mediaTypes.'json'] instead of [mediaTypes.'application/json']); typos like 'text\\html'; defining outputFormats with a mediaType value that is a bare name; programmatic use of the media package with file extensions instead of MIME strings.","solutions":["Fix the media type key/value in your config to the full 'mainType/subType' form, e.g. 'application/json' not 'json'.","Check custom outputFormats entries — their mediaType must reference a full MIME string that exists under mediaTypes.","If calling media.FromString in code, pass a MIME string, not a file extension; use FromStringAndExt to attach extensions."],"exampleFix":"# before (hugo.toml)\n[mediaTypes.\"jsonfeed\"]\nsuffixes = [\"json\"]\n\n# after\n[mediaTypes.\"application/feed+json\"]\nsuffixes = [\"json\"]","handlingStrategy":"validation","validationCode":"// Validate media type string before passing to Hugo config\nimport \"mime\"\nif _, _, err := mime.ParseMediaType(mt); err != nil || !strings.Contains(mt, \"/\") {\n    return fmt.Errorf(\"invalid media type %q: must be main/sub form\", mt)\n}","typeGuard":null,"tryCatchPattern":"types, err := media.DecodeTypes(...)\nif err != nil {\n    var pe *media.ParseError // or match message\n    log.Fatalf(\"media type config invalid: %v\", err)\n}","preventionTips":["Always write media types as main/subtype (e.g. text/html), never bare names","Validate custom mediaTypes config entries with mime.ParseMediaType before building","Copy suffix/delimiter settings from Hugo's built-in media type list rather than inventing formats"],"tags":["hugo","media-types","config","mime"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}