{"record":{"id":"f84cd082492e5515","repo":"gastownhall/beads","slug":"directory-path-is-empty","errorCode":null,"errorMessage":"directory path is empty","messagePattern":"directory path is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/directory_size.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io/fs\"\n\t\"math\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\ntype directoryWalkFunc func(string, filepath.WalkFunc) error\n\n// MeasureDirectorySize returns the approximate size of the live file tree at\n// root. It tolerates descendants disappearing while the tree is being walked,\n// but a missing root or any other filesystem error is a failed measurement.\nfunc MeasureDirectorySize(ctx context.Context, root string) (int64, error) {\n\tif root == \"\" {\n\t\treturn 0, fmt.Errorf(\"directory path is empty\")\n\t}\n\n\tresolvedRoot, err := filepath.EvalSymlinks(root)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tinfo, err := os.Stat(resolvedRoot)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif !info.IsDir() {\n\t\treturn 0, fmt.Errorf(\"%s is not a directory\", root)\n\t}\n\n\treturn measureDirectorySizeWithWalk(ctx, resolvedRoot, filepath.Walk)\n}\n\nfunc measureDirectorySizeWithWalk(ctx context.Context, root string, walk directoryWalkFunc) (int64, error) {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/directory_size.go#L2-L38","documentation":"MeasureDirectorySize measures the approximate size of a live file tree, but rejects an empty root path up front with this sentinel error rather than attempting a walk. It is a caller-contract validation error, not a filesystem failure.","triggerScenarios":"MeasureDirectorySize(ctx, \"\") — passing an uninitialized/empty string variable for the directory root, e.g. a config field that was never populated.","commonSituations":"Config struct not filled in (missing CLI flag or env var default); a path variable shadowed/zeroed by an earlier error path; programmatic callers constructing the root via string concatenation that produced \"\".","solutions":["Validate the root path is non-empty before calling; check the config/flag that supplies it","Fail fast at startup with a clear 'data directory not configured' message","Apply os.Getenv/flag defaults so the directory setting can never be empty in practice"],"exampleFix":"// before\nsize, err := storage.MeasureDirectorySize(ctx, cfg.DataDir) // cfg.DataDir == \"\"\n// after\nif cfg.DataDir == \"\" {\n    return fmt.Errorf(\"data directory not configured\")\n}\nsize, err := storage.MeasureDirectorySize(ctx, cfg.DataDir)","handlingStrategy":"validation","validationCode":"func validateRoot(root string) error {\n    if strings.TrimSpace(root) == \"\" {\n        return fmt.Errorf(\"data directory not configured\")\n    }\n    return nil\n}\n// call before MeasureDirectorySize","typeGuard":null,"tryCatchPattern":"if err := validateRoot(cfg.DataDir); err != nil { return err }\nsize, err := storage.MeasureDirectorySize(ctx, cfg.DataDir)\nif err != nil { return fmt.Errorf(\"measure %s: %w\", cfg.DataDir, err) }","preventionTips":["Fail fast at config load if the data-directory flag/env var is empty","Use a typed config accessor that returns an error for missing required paths","Cover the empty-path case in unit tests (the repo already tests this behavior)"],"tags":["go","validation","filesystem","configuration"],"backgroundTag":"missing-path-argument","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}