{"record":{"id":"883f969a0771b174","repo":"charmbracelet/crush","slug":"failed-to-tail-log-file-v","errorCode":null,"errorMessage":"failed to tail log file: %v","messagePattern":"failed to tail log file: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/logs.go","lineNumber":85,"sourceCode":"\t\t}\n\n\t\treturn showLogs(logsFile, tailLines)\n\t},\n}\n\nfunc init() {\n\tlogsCmd.Flags().BoolP(\"follow\", \"f\", false, \"Follow log output\")\n\tlogsCmd.Flags().IntP(\"tail\", \"t\", defaultTailLines, \"Show only the last N lines default: 1000 for performance\")\n}\n\nfunc followLogs(ctx context.Context, logsFile string, tailLines int) error {\n\tt, err := tail.TailFile(logsFile, tail.Config{\n\t\tFollow: false,\n\t\tReOpen: false,\n\t\tLogger: tail.DiscardingLogger,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to tail log file: %v\", err)\n\t}\n\n\tvar lines []string\n\tfor line := range t.Lines {\n\t\tif line.Err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tlines = append(lines, line.Text)\n\t\tif len(lines) > tailLines {\n\t\t\tlines = lines[len(lines)-tailLines:]\n\t\t}\n\t}\n\tt.Stop()\n\n\tfor _, line := range lines {\n\t\tprintLogLine(line)\n\t}\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/logs.go#L67-L103","documentation":"followLogs opens the crush.log file with the hpcloud/tail library's tail.TailFile (Follow:false, ReOpen:false). If the file cannot be opened or a tailer cannot be created (missing file, permission denied, path is a directory), the error is wrapped with this message. Note the follow path uses Follow:false here, so it reads currently available lines only.","triggerScenarios":"Calling followLogs with a logsFile path that does not exist (log file deleted between the os.Stat check and the tail), is unreadable due to permissions, or is a directory; also exotic cases like the file being on a filesystem tail cannot poll.","commonSituations":"Running `crush logs` right after cleaning the data directory; log file permissions changed by another process; custom --data-dir pointing somewhere without a logs/crush.log; race between project shutdown and log viewing.","solutions":["Verify the log file exists and is readable: ls -l <data-dir>/logs/crush.log; fix permissions with chmod if needed.","Ensure you are passing the correct --data-dir / --cwd so the resolved path points to a real crush project.","Re-run the crush project once to (re)generate the log file, then view logs.","If developing, re-check the file after os.Stat and fall back to a friendly 'no logs' message instead of the raw tail error."],"exampleFix":"// before\nif _, err = os.Stat(logsFile); os.IsNotExist(err) {\n    log.Warn(\"no logs\")\n    return nil\n}\n// after: also handle open failure gracefully\nif _, err = os.Stat(logsFile); os.IsNotExist(err) {\n    log.Warn(\"Looks like you are not in a crush project. No logs found.\")\n    return nil\n}\nif err := os.Chmod(logsFile, 0o644); err != nil { /* inspect */ }","handlingStrategy":"validation","validationCode":"// Go: ensure the log file exists and is readable before tailing\nif fi, err := os.Stat(logsFile); err != nil || fi.IsDir() {\n    return fmt.Errorf(\"log file unavailable: %s\", logsFile)\n}\nif f, err := os.Open(logsFile); err != nil {\n    return fmt.Errorf(\"log file unreadable: %w\", err)\n} else {\n    f.Close()\n}","typeGuard":null,"tryCatchPattern":"t, err := tail.TailFile(logsFile, tail.Config{Follow: false, ReOpen: false, Logger: tail.DiscardingLogger})\nif err != nil {\n    if os.IsNotExist(errors.Unwrap(err)) || errors.Is(err, fs.ErrNotExist) {\n        log.Warn(\"No logs found.\")\n        return nil\n    }\n    return fmt.Errorf(\"failed to tail log file: %w\", err)\n}","preventionTips":["Confirm the crush project has run at least once so the log exists.","Pass the correct --cwd/--data-dir to resolve the right log path.","Check permissions on <data-dir>/logs/crush.log.","Handle fs.ErrNotExist distinctly from other tail failures."],"tags":["filesystem","logging","cli"],"backgroundTag":"log-file-unreadable","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}