{"record":{"id":"140ec6af61905d5b","repo":"uber-go/zap","slug":"can-t-parse-q-as-a-url-v","errorCode":null,"errorMessage":"can't parse %q as a URL: %v","messagePattern":"can't parse %q as a URL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sink.go","lineNumber":104,"sourceCode":"\tif _, ok := sr.factories[normalized]; ok {\n\t\treturn fmt.Errorf(\"sink factory already registered for scheme %q\", normalized)\n\t}\n\tsr.factories[normalized] = factory\n\treturn nil\n}\n\nfunc (sr *sinkRegistry) newSink(rawURL string) (Sink, error) {\n\t// URL parsing doesn't work well for Windows paths such as `c:\\log.txt`, as scheme is set to\n\t// the drive, and path is unset unless `c:/log.txt` is used.\n\t// To avoid Windows-specific URL handling, we instead check IsAbs to open as a file.\n\t// filepath.IsAbs is OS-specific, so IsAbs('c:/log.txt') is false outside of Windows.\n\tif filepath.IsAbs(rawURL) {\n\t\treturn sr.newFileSinkFromPath(rawURL)\n\t}\n\n\tu, err := url.Parse(rawURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"can't parse %q as a URL: %v\", rawURL, err)\n\t}\n\tif u.Scheme == \"\" {\n\t\tu.Scheme = schemeFile\n\t}\n\n\tsr.mu.Lock()\n\tfactory, ok := sr.factories[u.Scheme]\n\tsr.mu.Unlock()\n\tif !ok {\n\t\treturn nil, &errSinkNotFound{u.Scheme}\n\t}\n\treturn factory(u)\n}\n\n// RegisterSink registers a user-supplied factory for all sinks with a\n// particular scheme.\n//\n// All schemes must be ASCII, valid under section 0.1 of RFC 3986","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/uber-go/zap/blob/bbd4ecbd8760678fdbac94c93d9aca8069c83b2f/sink.go#L86-L122","documentation":"newSink parses the log destination string as a URL after checking for absolute paths; if url.Parse fails, this error wraps the parse error. It means the value passed to zap.Open / zap.Config.Build (the log sink URL) is not a parseable URL string.","triggerScenarios":"Calling zap.Open(\"http://[bad::url\") or Build with an Outputs entry containing unescaped characters (spaces, stray '%', unbalanced brackets), or control characters in a path derived from config/env.","commonSituations":"Windows-style paths with backslashes or drive letters fed as URLs; URLs with raw spaces copied from documentation; config interpolations producing 'file://%VAR%' with malformed values.","solutions":["Fix the URL syntax in your config (quote/escape spaces and special characters, balance IPv6 brackets).","Use plain absolute file paths (e.g. /var/log/app.log) instead of file:// URLs when logging to files.","Validate the destination with url.Parse in your own code and report a clear config error before constructing the logger."],"exampleFix":"// before\nlogger, _ := zap.Open(\"file://my logs/app.log\") // space breaks parsing\n// after\nlogger, _ := zap.Open(\"/var/log/myapp/app.log\")","handlingStrategy":"validation","validationCode":"func validSinkURL(raw string) error {\n    if filepath.IsAbs(raw) {\n        return nil\n    }\n    if _, err := url.Parse(raw); err != nil {\n        return fmt.Errorf(\"invalid sink URL %q: %w\", raw, err)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"logger, err := cfg.Build()\nif err != nil {\n    if strings.Contains(err.Error(), \"can't parse\") {\n        return fmt.Errorf(\"check log output URLs in config: %w\", err)\n    }\n    return err\n}","preventionTips":["Prefer plain absolute paths for file outputs","Escape or quote special characters in URL values in config files","Validate every Outputs entry with url.Parse during config load"],"tags":["zap","url","sink","configuration"],"backgroundTag":"url-parse-error","analyzedSha":"bbd4ecbd8760678fdbac94c93d9aca8069c83b2f","analyzedAt":"2026-08-31T13:01:40.228Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}