{"record":{"id":"de925311988f2898","repo":"golang/go","slug":"file-url-missing-drive-letter","errorCode":null,"errorMessage":"file URL missing drive letter","messagePattern":"file URL missing drive letter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/web/url_windows.go","lineNumber":40,"sourceCode":"\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":22,"sourceCodeEnd":44,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/web/url_windows.go#L22-L44","documentation":"Windows-specific (url_windows.go): after the host check passes, the function inspects path[1:] (the part after the leading slash) expecting a drive letter volume (like C:). If filepath.VolumeName returns empty or a UNC prefix (\"\\\\\"), the URL has no valid Windows drive and cannot be turned into a local path. This is the path-level equivalent of \"not a Windows absolute path.\"","triggerScenarios":"On Windows, passing a file: URL whose path is Unix-style (file:///home/me/x — no drive letter). Passing file://localhost/path where path lacks a drive. A file URL whose path is /share/dir interpreted as UNC but malformed.","commonSituations":"Cross-platform config files using Unix-style absolute paths on a Windows builder. CI matrices that share GOPATH/GOMODCACHE URLs across OSes without drive-letter translation. Mis-templated URL strings that omit the drive letter placeholder.","solutions":["On Windows, supply a drive-qualified path: file:///C:/Users/me/x.","Use web.URLFromFilePath(absPath) on a Windows absolute path; it emits the correct drive-bearing URL.","For network shares, use the UNC form file://host/share/... so the host branch handles it (errors 142/143 do not fire).","OS-gate your config: emit drive-qualified URLs only when runtime.GOOS == \"windows\"."],"exampleFix":"// before (on Windows)\nu, _ := url.Parse(\"file:///Users/me/app\")\n_, err := web.URLToFilePath(u) // -> \"missing drive letter\"\n\n// after\nu, _ := url.Parse(\"file:///C:/Users/me/app\")\n_, err := web.URLToFilePath(u)","handlingStrategy":"validation","validationCode":"// On Windows, require a drive-qualified path\nif runtime.GOOS == \"windows\" {\n    rel := strings.TrimPrefix(u.Path, \"/\")\n    if filepath.VolumeName(rel) == \"\" {\n        return errors.New(\"file URL path lacks a Windows drive letter\")\n    }\n}","typeGuard":"func hasWindowsDrive(u *url.URL) bool {\n    p := strings.TrimPrefix(u.Path, \"/\")\n    return filepath.VolumeName(p) != \"\" && !strings.HasPrefix(filepath.VolumeName(p), `\\\\`)\n}","tryCatchPattern":null,"preventionTips":["On Windows, always derive file URLs from filepath.Abs-qualified paths.","Do not share Unix-style file URLs into Windows builds.","OS-gate URL construction in cross-platform tooling."],"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"}