{"record":{"id":"39c8ace6592a97d7","repo":"wavetermdev/waveterm","slug":"failed-to-expand-path-w-39c8ac","errorCode":null,"errorMessage":"failed to expand path: %w","messagePattern":"failed to expand path: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/fileutil/readdir.go","lineNumber":41,"sourceCode":"\tMode         string `json:\"mode\"`\n\tModified     string `json:\"modified\"`\n\tModifiedTime string `json:\"modified_time\"`\n}\n\ntype ReadDirResult struct {\n\tPath         string        `json:\"path\"`\n\tAbsolutePath string        `json:\"absolute_path\"`\n\tParentDir    string        `json:\"parent_dir,omitempty\"`\n\tEntries      []DirEntryOut `json:\"entries\"`\n\tEntryCount   int           `json:\"entry_count\"`\n\tTotalEntries int           `json:\"total_entries\"`\n\tTruncated    bool          `json:\"truncated,omitempty\"`\n}\n\nfunc ReadDir(path string, maxEntries int) (*ReadDirResult, error) {\n\texpandedPath, err := wavebase.ExpandHomeDir(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to expand path: %w\", err)\n\t}\n\n\tfileInfo, err := os.Stat(expandedPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to stat path: %w\", err)\n\t}\n\n\tif !fileInfo.IsDir() {\n\t\treturn nil, fmt.Errorf(\"path is not a directory\")\n\t}\n\n\tentries, err := os.ReadDir(expandedPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read directory: %w\", err)\n\t}\n\n\ttotalEntries := len(entries)\n","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/util/fileutil/readdir.go#L23-L59","documentation":"ReadDir first normalizes its input with wavebase.ExpandHomeDir (resolving ~/ and ~user/ prefixes); if that expansion itself errors, the failure is wrapped here. Expansion fails on malformed home-relative paths or when the user's home directory cannot be determined.","triggerScenarios":"Calling ReadDir with a path like \"~/x\" or \"~\" where wavebase.ExpandHomeDir cannot resolve the home directory (e.g. HOME unset and no passwd entry for the current user, or a malformed '~user' with unknown user).","commonSituations":"Running inside a minimal container or service (systemd, cron) where HOME is not set; passing a literal path containing a stray '~'; a '~otheruser' path for a user that doesn't exist on the host.","solutions":["Pass an absolute path instead of a ~-relative one.","Check the HOME environment variable is set for the process user (`echo $HOME`), or run via a login shell.","If using '~user' syntax, confirm that user exists in /etc/passwd on the host.","Call wavebase.ExpandHomeDir yourself first to see the precise underlying error."],"exampleFix":"// before\nfileutil.ReadDir(\"~/logs\", 100)\n// after\nfileutil.ReadDir(\"/home/alice/logs\", 100)","handlingStrategy":"validation","validationCode":"if strings.HasPrefix(path, \"~\") && os.Getenv(\"HOME\") == \"\" {\n\treturn fmt.Errorf(\"HOME is not set; pass an absolute path instead of %q\", path)\n}\nabs, err := wavebase.ExpandHomeDir(path)\nif err != nil { return err }","typeGuard":null,"tryCatchPattern":"res, err := fileutil.ReadDir(path, max)\nif err != nil && strings.Contains(err.Error(), \"failed to expand path\") {\n\t// fall back to the literal path or prompt the user for an absolute path\n}","preventionTips":["Prefer absolute paths in configs and API calls; reserve ~ for interactive use.","Ensure HOME is set when running under systemd, cron, or containers.","Validate '~user' references exist on the host before use."],"tags":["filesystem","go","path","home-directory"],"backgroundTag":"home-dir-not-set","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}