{"record":{"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/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/media/mediaType.go#L123-L159","documentation":"Returned by media.FromString when the input string does not split into exactly two parts on '/'. FromString expects 'MainType/SubType' (optionally 'MainType/SubType+suffix'); anything without exactly one slash, or with more than one, is rejected. This is the root cause often wrapped by 449.","triggerScenarios":"Calling media.FromString(t) with a string like \"markdown\", \"text/html/extra\", or \"\" (empty). Indirectly via DecodeTypes when a [mediaTypes] key is malformed. Also called from FromStringAndExt and content type lookups.","commonSituations":"Typing a bare subtype as a media type key; copying an extension instead of the MIME; trailing slash ('text/'); multiple slashes from path concatenation; an empty string from a missing config value.","solutions":["Provide a value of the form 'MainType/SubType', e.g. 'text/html'.","Use the optional '+suffix' form only when needed: 'application/rss+xml'.","Check for accidental empty strings or path-like values passed where a MIME is expected."],"exampleFix":"// before\nmedia.FromString(\"markdown\")   // error: cannot parse \"markdown\"\n\n// after\nmedia.FromString(\"text/markdown\")","handlingStrategy":"validation","validationCode":"// Validate a MIME string the way FromString does, before calling it.\nfunc validMime(t string) bool {\n    t = strings.ToLower(t)\n    parts := strings.Split(t, \"/\")\n    return len(parts) == 2 && parts[0] != \"\" && !strings.Contains(parts[1], \"/\")\n}","typeGuard":"func isValidMediaType(t string) bool {\n    parts := strings.Split(strings.ToLower(t), \"/\")\n    if len(parts) != 2 {\n        return false\n    }\n    return parts[0] != \"\" && !strings.Contains(parts[1], \"/\")\n}","tryCatchPattern":"if _, err := media.FromString(t); err != nil {\n    // fall back to a known-good default or reject the config\n    return fmt.Errorf(\"invalid media type %q: %w\", t, err)\n}","preventionTips":["Always pass 'MainType/SubType' to FromString.","Use the '+suffix' form only for structured suffixes (e.g. '+xml').","Validate config-sourced MIME strings before use."],"tags":["media-types","mime","parsing","validation"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}