{"record":{"id":"c549c1ebf003daf0","repo":"charmbracelet/glow","slug":"invalid-url-s-c549c1","errorCode":null,"errorMessage":"invalid url: %s","messagePattern":"invalid url: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitlab.go","lineNumber":17,"sourceCode":"package main\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// findGitLabREADME tries to find the correct README filename in a repository using GitLab API.\nfunc findGitLabREADME(u *url.URL) (*source, error) {\n\towner, repo, ok := strings.Cut(strings.TrimPrefix(u.Path, \"/\"), \"/\")\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid url: %s\", u.String())\n\t}\n\n\tprojectPath := url.QueryEscape(owner + \"/\" + repo)\n\n\ttype readme struct {\n\t\tReadmeURL string `json:\"readme_url\"`\n\t}\n\n\tapiURL := fmt.Sprintf(\"https://%s/api/v4/projects/%s\", u.Hostname(), projectPath)\n\n\t//nolint:bodyclose\n\t// it is closed on the caller\n\tres, err := http.Get(apiURL) //nolint: gosec,noctx\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to get url: %w\", err)\n\t}\n\n\tbody, err := io.ReadAll(res.Body)","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/charmbracelet/glow/blob/e3970c813d93da1ea84edfca90c289d9afb82242/gitlab.go#L1-L35","documentation":"findGitLabREADME mirrors the GitHub path parsing: it cuts the trimmed URL path on the first '/' to get owner and project. With fewer than two path segments, ok is false and this error reports the full URL before any request is made. It is a URL-shape validation failure only.","triggerScenarios":"Passing https://gitlab.com alone; a user or group page like https://gitlab.com/mygroup; a project URL with an empty project segment; hand-built URLs where the project component is blank.","commonSituations":"Copying a group/subgroup landing page instead of a project; scripts templating the project field from an empty variable; truncated pastes.","solutions":["Use the full project URL: https://gitlab.com/OWNER/PROJECT","When constructing URLs in code, require both owner and project to be non-empty","Navigate into an actual project page before copying the URL"],"exampleFix":"# before\nglow https://gitlab.com/mygroup   # group page, no project\n\n# after\nglow https://gitlab.com/mygroup/myproject","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isGitLabProjectURL(u *url.URL) bool {\n\tif u == nil || (u.Host != \"gitlab.com\" && !strings.HasSuffix(u.Host, \".gitlab.com\")) {\n\t\treturn false\n\t}\n\t_, _, ok := strings.Cut(strings.TrimPrefix(u.Path, \"/\"), \"/\")\n\treturn ok\n}\n\nif !isGitLabProjectURL(u) {\n\treturn fmt.Errorf(\"expected https://gitlab.com/OWNER/PROJECT, got %s\", u)\n}","tryCatchPattern":"src, err := findGitLabREADME(u)\nif err != nil && strings.Contains(err.Error(), \"invalid url\") {\n\t// deterministic shape failure — do not retry; request a proper project URL\n\treturn nil, fmt.Errorf(\"need owner/project URL like https://gitlab.com/OWNER/PROJECT: %w\", err)\n}\nreturn src, err","preventionTips":["Require both owner and project segments when constructing GitLab URLs programmatically","Copy URLs from a project page, not a group/profile page","Unit-test URL builders with table-driven cases: empty repo, single segment, trailing slash"],"tags":["url","validation","gitlab","parsing"],"backgroundTag":null,"analyzedSha":"e3970c813d93da1ea84edfca90c289d9afb82242","analyzedAt":"2026-08-15T22:50:54.304Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}