{"record":{"id":"9dc1a8ca423c9812","repo":"golang/go","slug":"file-url-encodes-volume-in-host-field-too-few-sla","errorCode":null,"errorMessage":"file URL encodes volume in host field: too few slashes?","messagePattern":"file URL encodes volume in host field: too few slashes\\?","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/web/url_windows.go","lineNumber":32,"sourceCode":"\tif len(path) == 0 || path[0] != '/' {\n\t\treturn \"\", errNotAbsolute\n\t}\n\n\tpath = filepath.FromSlash(path)\n\n\t// We interpret Windows file URLs per the description in\n\t// https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/.\n\n\t// The host part of a file URL (if any) is the UNC volume name,\n\t// but RFC 8089 reserves the authority \"localhost\" for the local machine.\n\tif host != \"\" && host != \"localhost\" {\n\t\t// A common \"legacy\" format omits the leading slash before a drive letter,\n\t\t// encoding the drive letter as the host instead of part of the path.\n\t\t// (See https://blogs.msdn.microsoft.com/freeassociations/2005/05/19/the-bizarre-and-unhappy-story-of-file-urls/.)\n\t\t// We do not support that format, but we should at least emit a more\n\t\t// helpful error message for it.\n\t\tif filepath.VolumeName(host) != \"\" {\n\t\t\treturn \"\", errors.New(\"file URL encodes volume in host field: too few slashes?\")\n\t\t}\n\t\treturn `\\\\` + host + path, nil\n\t}\n\n\t// If host is empty, path must contain an initial slash followed by a\n\t// drive letter and path. Remove the slash and verify that the path is valid.\n\tif vol := filepath.VolumeName(path[1:]); vol == \"\" || strings.HasPrefix(vol, `\\\\`) {\n\t\treturn \"\", errors.New(\"file URL missing drive letter\")\n\t}\n\treturn path[1:], nil\n}\n","sourceCodeStart":14,"sourceCodeEnd":44,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/web/url_windows.go#L14-L44","documentation":"Windows-specific (url_windows.go): convertFileURLPath detects that the host portion of a file: URL looks like a Windows drive letter (e.g. file://C:/path — only two slashes after file:). This is the well-known broken legacy format where the drive letter is encoded as the host. The go command refuses to support it and emits a hint pointing at the missing slash, because accepting it would silently mis-parse many URLs.","triggerScenarios":"On Windows, parsing \"file://C:/Users/me/x\" (two slashes) instead of \"file:///C:/Users/me/x\" (three slashes). Configuration files or build logs that emit file://C: URLs from naive join logic. URL builders that concatenate \"file://\" + drivePath without accounting for the leading slash.","commonSituations":"Copy-pasting Windows file URLs from browsers or emails that drop the third slash. Tools that produce URLs via \"file://\" + filepath.ToSlash(path) where path starts with \"C:\\\". Documentation written by authors unfamiliar with the three-slash Windows convention.","solutions":["Use three slashes for local Windows paths: file:///C:/Users/me/x so the host is empty and the drive lives in Path.","Build Windows file URLs with web.URLFromFilePath(absPath) which always emits the correct form.","When interpolating, do \"file:///\" + filepath.ToSlash(path) — never \"file://\" + path.","Add a lint check that flags file://<single-letter>: patterns in config files."],"exampleFix":"// before\nu, _ := url.Parse(\"file://C:/Users/me/app\")\n_, err := web.URLToFilePath(u) // -> \"encodes volume in host field\"\n\n// after\nu, _ := url.Parse(\"file:///C:/Users/me/app\")\n_, err := web.URLToFilePath(u)","handlingStrategy":"validation","validationCode":"// reject the legacy two-slash drive-letter form on Windows\nif runtime.GOOS == \"windows\" && u.Host != \"\" && u.Host != \"localhost\" &&\n    filepath.VolumeName(u.Host) != \"\" {\n    return errors.New(\"rewrite as file:///\" + u.Host + u.Path)\n}","typeGuard":"func isWellFormedWindowsFileURL(u *url.URL) bool {\n    if u.Scheme != \"file\" { return false }\n    if u.Host == \"\" || u.Host == \"localhost\" { return true }\n    return filepath.VolumeName(u.Host) == \"\"\n}","tryCatchPattern":null,"preventionTips":["Always emit three slashes for local Windows file URLs (file:///C:/...).","Use web.URLFromFilePath to construct Windows file URLs correctly.","Add a CI lint that flags file://[A-Za-z]: patterns."],"tags":["go-toolchain","url","file-url","windows","validation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}