{"record":{"id":"38cfea7b1b562132","repo":"uber-go/zap","slug":"open-sink-q-w","errorCode":null,"errorMessage":"open sink %q: %w","messagePattern":"open sink %q: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"writer.go","lineNumber":73,"sourceCode":"\n\twriter := CombineWriteSyncers(writers...)\n\treturn writer, closeAll, nil\n}\n\nfunc open(paths []string) ([]zapcore.WriteSyncer, func(), error) {\n\twriters := make([]zapcore.WriteSyncer, 0, len(paths))\n\tclosers := make([]io.Closer, 0, len(paths))\n\tcloseAll := func() {\n\t\tfor _, c := range closers {\n\t\t\t_ = c.Close()\n\t\t}\n\t}\n\n\tvar openErr error\n\tfor _, path := range paths {\n\t\tsink, err := _sinkRegistry.newSink(path)\n\t\tif err != nil {\n\t\t\topenErr = multierr.Append(openErr, fmt.Errorf(\"open sink %q: %w\", path, err))\n\t\t\tcontinue\n\t\t}\n\t\twriters = append(writers, sink)\n\t\tclosers = append(closers, sink)\n\t}\n\tif openErr != nil {\n\t\tcloseAll()\n\t\treturn nil, nil, openErr\n\t}\n\n\treturn writers, closeAll, nil\n}\n\n// CombineWriteSyncers is a utility that combines multiple WriteSyncers into a\n// single, locked WriteSyncer. If no inputs are supplied, it returns a no-op\n// WriteSyncer.\n//\n// It's provided purely as a convenience; the result is no different from","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/uber-go/zap/blob/bbd4ecbd8760678fdbac94c93d9aca8069c83b2f/writer.go#L55-L91","documentation":"When building a logger, zap Open()s each configured output path (via Build option Open or Config.Build). If any sink fails to open, the error is wrapped per-path as \"open sink %q: %w\" and collected with multierr, so one report enumerates every failing output path and its underlying cause (e.g. permission denied, bad scheme, no registered sink).","triggerScenarios":"zap.Open(paths...) or cfg.Build() with an output path whose scheme has no registered sink factory, a file that cannot be created (permissions, missing directory), or an invalid URL.","commonSituations":"Log file paths in config pointing to read-only or nonexistent directories; typo'd or unregistered sink scheme like \"kafka://...\" without RegisterSink; container/user without write permission to /var/log; running as a different user in Docker.","solutions":["Read the wrapped cause for each path: register missing sink schemes via zap.RegisterSink or fix the path (create directory, fix permissions).","Ensure output directories exist before building the logger (os.MkdirAll on the file's directory).","Check file permissions / run the process as a user that can write to the configured log path.","If the path should be stderr/stdout, use \"stderr\"/\"stdout\" instead of a custom scheme."],"exampleFix":"// before\ncfg.OutputPaths = []string{\"/var/log/app.log\"} // dir missing\n// after\nos.MkdirAll(\"/var/log\", 0o755)\ncfg.OutputPaths = []string{\"/var/log/app.log\"}","handlingStrategy":"validation","validationCode":"for _, p := range cfg.OutputPaths {\n    if p != \"stderr\" && p != \"stdout\" && !strings.Contains(p, \"://\") {\n        if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {\n            return err\n        }\n    }\n}\nlogger, err := cfg.Build()","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var me multierr.Error\n    if errors.As(err, &me) {\n        for _, e := range me.Errors() {\n            log.Printf(\"sink failure: %v\", e)\n        }\n    }\n    return fmt.Errorf(\"logger init: %w\", err)\n}","preventionTips":["Create log directories at startup before building the logger.","Register all custom sink schemes before cfg.Build/Open is called.","Prefer stderr/stdout in containerized environments instead of file paths.","Check that the process user has write permission on configured log paths."],"tags":["sink","file-io","logger-config"],"backgroundTag":"log-output-open-failed","analyzedSha":"bbd4ecbd8760678fdbac94c93d9aca8069c83b2f","analyzedAt":"2026-08-31T13:01:40.228Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}