{"record":{"id":"acbbfc096eaea957","repo":"cloudflare/cloudflared","slug":"error-reading-directory-s-w","errorCode":null,"errorMessage":"error reading directory %s: %w","messagePattern":"error reading directory (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"diagnostic/log_collector_utils.go","lineNumber":77,"sourceCode":"\t\treturn nil, fmt.Errorf(\n\t\t\t\"error waiting from command '%s': %w\",\n\t\t\tcommand.String(),\n\t\t\terr,\n\t\t)\n\t}\n\n\treturn NewLogInformation(outputHandle.Name(), true, false), nil\n}\n\nfunc CopyFilesFromDirectory(path string) (string, error) {\n\tconst defaultLogFilename = \"cloudflared.log\"\n\n\t// rolling logs have as suffix the current date thus\n\t// when iterating the path files they are already in\n\t// chronological order\n\tfiles, err := os.ReadDir(path)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error reading directory %s: %w\", path, err)\n\t}\n\n\t// nolint: gosec\n\toutputHandle, err := os.Create(filepath.Join(os.TempDir(), logFilename))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"creating temporary log file %s: %w\", logFilename, err)\n\t}\n\tdefer func() { _ = outputHandle.Close() }()\n\n\tfor _, file := range files {\n\t\t// nolint: gosec\n\t\tlogHandle, err := os.Open(filepath.Join(path, file.Name()))\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"error opening file %s: %w\", file.Name(), err)\n\t\t}\n\t\t_, err = io.Copy(outputHandle, logHandle)\n\t\t_ = logHandle.Close()\n\t\tif err != nil {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/diagnostic/log_collector_utils.go#L59-L95","documentation":"Wrapped os.ReadDir failure in diagnostic CopyFilesFromDirectory: the directory holding cloudflared's rolling log files could not be read (wrong path, missing directory, or permissions), so the diagnostic log-collection bundle cannot be assembled.","triggerScenarios":"os.ReadDir(path) fails during diagnostic log collection: the log directory does not exist, was rotated/deleted, or the process lacks read permission on it.","commonSituations":"cloudflared log directory moved or cleaned up before 'diagnostic collect' ran; path typo in configuration; running as a user without access to the log dir.","solutions":["Verify the directory path exists and is readable (ls -ld <path>)","Recreate/point configuration at the correct cloudflared log directory","Run the diagnostic as a user with permission to read the log directory"],"exampleFix":"// before\nerr := diagnostic.CopyFilesFromDirectory(ctx, fs, unknownPath, ...)\n// after\nif _, err := os.Stat(logDir); err != nil { fixPath() }\nerr := diagnostic.CopyFilesFromDirectory(ctx, fs, logDir, ...)","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(path)\nif err != nil { return fmt.Errorf(\"log dir missing: %w\", err) }\nif !fi.IsDir() { return fmt.Errorf(\"%s is not a directory\", path) }\nif _, err := os.ReadDir(path); err != nil { return err }","typeGuard":"func isReadableDir(path string) bool {\n\tfi, err := os.Stat(path)\n\treturn err == nil && fi.IsDir()\n}","tryCatchPattern":"out, err := diagnostic.CopyFilesFromDirectory(ctx, fs, logDir, logFilename)\nif err != nil && strings.Contains(err.Error(), \"error reading directory\") {\n\t// fall back to default log dir or skip\n}","preventionTips":["Resolve the log directory from config before collecting","Recreate the log dir if cleanup jobs removed it","Run the collector with read access to the log dir"],"tags":["filesystem","directory","diagnostics"],"backgroundTag":"directory-not-found","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}