{"record":{"id":"1c3f20edc9e9d5f7","repo":"usememos/memos","slug":"not-a-html-page","errorCode":null,"errorMessage":"not a HTML page","messagePattern":"not a HTML page","errorType":"http","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/httpgetter/html_meta.go","lineNumber":152,"sourceCode":"}\n\nfunc GetHTMLMeta(urlStr string) (*HTMLMeta, error) {\n\tif err := validateURL(urlStr); err != nil {\n\t\treturn nil, err\n\t}\n\n\tresponse, err := httpClient.Get(urlStr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer response.Body.Close()\n\n\tmediatype, err := getMediatype(response)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif mediatype != \"text/html\" {\n\t\treturn nil, errors.New(\"not a HTML page\")\n\t}\n\n\thtmlMeta := extractHTMLMeta(io.LimitReader(response.Body, maxHTMLMetaBytes))\n\tenrichSiteMeta(response.Request.URL, htmlMeta)\n\treturn htmlMeta, nil\n}\n\nfunc extractHTMLMeta(resp io.Reader) *HTMLMeta {\n\ttokenizer := html.NewTokenizer(resp)\n\thtmlMeta := new(HTMLMeta)\n\n\tfor {\n\t\ttokenType := tokenizer.Next()\n\t\tif tokenType == html.ErrorToken {\n\t\t\tbreak\n\t\t} else if tokenType == html.StartTagToken || tokenType == html.SelfClosingTagToken {\n\t\t\ttoken := tokenizer.Token()\n\t\t\tif token.DataAtom == atom.Body {","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/httpgetter/html_meta.go#L134-L170","documentation":"The HTML metadata getter fetched the URL successfully but the response Content-Type was not exactly text/html, so there is no HTML to extract a title/description from. The check is on the parsed mediatype, so parameters like charset are stripped first.","triggerScenarios":"Fetching a PDF, image, JSON API endpoint, plain-text file, or a download link (Content-Disposition attachments often serve application/octet-stream) through the link-preview path.","commonSituations":"Pasting a direct link to a PDF, raw GitHub file, image, or API endpoint into a memo; servers misconfigured to serve HTML pages as text/plain; endpoints that content-negotiate to JSON for non-browser clients.","solutions":["Link to the HTML page that embeds/links the resource, not the resource itself","If you own the server, ensure HTML pages are served with `Content-Type: text/html; charset=utf-8`","Handle this error gracefully in UI: skip preview generation instead of showing a failure"],"exampleFix":"// before\nGetHTMLMeta(\"https://example.com/report.pdf\")\n// after\nGetHTMLMeta(\"https://example.com/reports/report\") // HTML landing page","handlingStrategy":"try-catch","validationCode":"// Optional pre-check via HEAD (best effort; server may lie)\nfunc looksLikeHTML(u string) bool {\n  resp, err := http.Head(u)\n  if err != nil { return true } // let the real fetcher decide\n  ct := resp.Header.Get(\"Content-Type\")\n  return strings.HasPrefix(ct, \"text/html\")\n}","typeGuard":null,"tryCatchPattern":"// Not-a-page is expected for non-HTML links: skip the preview silently\nif _, err := getter.GetHTMLMeta(u); err != nil {\n  if strings.Contains(err.Error(), \"not a HTML page\") { return nil }\n  return err\n}","preventionTips":["Treat metadata extraction as best-effort; never fail note creation for it","Prefer linking to HTML landing pages over raw files","Check Content-Type handling if you control the target server"],"tags":["network","http","content-type"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}