{"record":{"id":"d52ecd0cb9de9ad4","repo":"uber-go/zap","slug":"user-and-password-not-allowed-with-file-urls-got","errorCode":null,"errorMessage":"user and password not allowed with file URLs: got %v","messagePattern":"user and password not allowed with file URLs: got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sink.go","lineNumber":132,"sourceCode":"\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\n// (https://tools.ietf.org/html/rfc3983#section-3.1), and must not already\n// have a factory registered. Zap automatically registers a factory for the\n// \"file\" scheme.\nfunc RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {\n\treturn _sinkRegistry.RegisterSink(scheme, factory)\n}\n\nfunc (sr *sinkRegistry) newFileSinkFromURL(u *url.URL) (Sink, error) {\n\tif u.User != nil {\n\t\treturn nil, fmt.Errorf(\"user and password not allowed with file URLs: got %v\", u)\n\t}\n\tif u.Fragment != \"\" {\n\t\treturn nil, fmt.Errorf(\"fragments not allowed with file URLs: got %v\", u)\n\t}\n\tif u.RawQuery != \"\" {\n\t\treturn nil, fmt.Errorf(\"query parameters not allowed with file URLs: got %v\", u)\n\t}\n\t// Error messages are better if we check hostname and port separately.\n\tif u.Port() != \"\" {\n\t\treturn nil, fmt.Errorf(\"ports not allowed with file URLs: got %v\", u)\n\t}\n\tif hn := u.Hostname(); hn != \"\" && hn != \"localhost\" {\n\t\treturn nil, fmt.Errorf(\"file URLs must leave host empty or use localhost: got %v\", u)\n\t}\n\n\treturn sr.newFileSinkFromPath(u.Path)\n}\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/uber-go/zap/blob/bbd4ecbd8760678fdbac94c93d9aca8069c83b2f/sink.go#L114-L150","documentation":"newFileSinkFromURL rejects file:// URLs that carry userinfo. Zap treats file URLs as plain filesystem paths, so a username/password component has no meaning and indicates a mistaken destination string.","triggerScenarios":"Passing a destination like file://user:pass@/var/log/app.log to zap.Open or Outputs; accidentally reusing an authenticated URL (e.g. an FTP or HTTP URL) with the file scheme.","commonSituations":"Config templating that swaps the scheme of an authenticated URL to file://; copy-paste from connection strings that include credentials.","solutions":["Remove the user:pass@ component from the file URL: use file:///var/log/app.log.","Use a plain absolute path (/var/log/app.log) instead of a file:// URL.","If you need credentials, you are likely targeting a network sink (e.g. a custom registered scheme), not file://."],"exampleFix":"// before\nzap.Open(\"file://admin:secret@/var/log/app.log\")\n// after\nzap.Open(\"file:///var/log/app.log\")","handlingStrategy":"validation","validationCode":"u, err := url.Parse(dest)\nif err == nil && u.Scheme == \"file\" && u.User != nil {\n    return fmt.Errorf(\"file URL must not contain credentials: %s\", dest)\n}","typeGuard":null,"tryCatchPattern":"if _, err := zap.Open(dest); err != nil {\n    if strings.Contains(err.Error(), \"user and password not allowed\") {\n        return fmt.Errorf(\"strip credentials from file URL %q\", dest)\n    }\n    return err\n}","preventionTips":["Never reuse authenticated network URLs as file:// destinations","Strip userinfo from URL values during config sanitization","Store credentials separately from log destination config"],"tags":["zap","file-sink","url","validation"],"backgroundTag":"invalid-file-url","analyzedSha":"bbd4ecbd8760678fdbac94c93d9aca8069c83b2f","analyzedAt":"2026-08-31T13:01:40.228Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}