{"record":{"id":"5a1a9a87a2a425f4","repo":"gastownhall/beads","slug":"failed-to-create-user-config-directory-w","errorCode":null,"errorMessage":"failed to create user config directory: %w","messagePattern":"failed to create user config directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/yaml_config.go","lineNumber":495,"sourceCode":"\t// uses (SetUserYamlConfig, setYamlConfigAtPath, the metrics bootstrap);\n\t// rewriting at 0644 would relax this shared user config to world-readable.\n\tif err := os.WriteFile(configPath, []byte(newContent), 0o600); err != nil { //nolint:gosec // configPath is from UserConfigYamlPath\n\t\treturn fmt.Errorf(\"failed to write user config.yaml: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc SetUserYamlConfig(key, value string) error {\n\tif err := validateYamlConfigValue(key, value); err != nil {\n\t\treturn err\n\t}\n\tconfigPath, err := UserConfigYamlPath()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := os.MkdirAll(filepath.Dir(configPath), 0o755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create user config directory: %w\", err)\n\t}\n\tif _, err := os.Stat(configPath); os.IsNotExist(err) {\n\t\tif err := os.WriteFile(configPath, []byte{}, 0o600); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create user config.yaml: %w\", err)\n\t\t}\n\t} else if err != nil {\n\t\treturn fmt.Errorf(\"failed to stat user config.yaml: %w\", err)\n\t}\n\treturn setYamlConfigAtPath(configPath, key, value)\n}\n\nfunc setYamlConfigAtPath(configPath, key, value string) error {\n\n\t// Normalize key to canonical yaml format\n\tnormalizedKey := normalizeYamlKey(key)\n\n\t// Read existing config\n\tcontent, err := os.ReadFile(configPath) //nolint:gosec // configPath is from findProjectConfigYaml","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/config/yaml_config.go#L477-L513","documentation":"SetUserYamlConfig resolves the user config path via UserConfigYamlPath, then ensures the parent directory exists with os.MkdirAll(dir, 0o755). If directory creation fails, the error is wrapped as 'failed to create user config directory'. This happens before any file is created or written.","triggerScenarios":"os.MkdirAll on the user config directory (e.g. ~/.beads) fails because HOME is unwritable, a non-directory file exists at the target path, or permission/ENOSPC/EROFS conditions apply.","commonSituations":"HOME pointing to a read-only or nonexistent location; a regular file named .beads blocking directory creation; restricted sandboxed CI runners with read-only HOME.","solutions":["Ensure a file named like the config dir doesn't already exist (e.g. ~/.beads as a file) — remove or rename it.","Fix HOME/USERPROFILE to a writable absolute path and retry.","Check permissions on the parent (chmod u+w ~) and free disk space if ENOSPC.","Read the wrapped %w cause (EACCES/ENOTDIR/EROFS) and fix the specific filesystem condition."],"exampleFix":"// before\n$ ls -la ~ | grep beads\n-rw-r--r-- 1 user user .beads     # a file, not a dir\nbd config set ... // mkdir fails ENOTDIR\n// after\nmv ~/.beads ~/.beads.bak\nmkdir -p ~/.beads\nbd config set ...","handlingStrategy":"validation","validationCode":"dir := filepath.Join(os.Getenv(\"HOME\"), \".beads\")\nif fi, err := os.Stat(dir); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"%s exists but is not a directory\", dir)\n}\nif err := unix.Access(filepath.Dir(dir), unix.W_OK); err != nil {\n    return fmt.Errorf(\"parent %s not writable: %w\", filepath.Dir(dir), err)\n}","typeGuard":null,"tryCatchPattern":"err := config.SetUserYamlConfig(key, value)\nif err != nil && strings.Contains(err.Error(), \"failed to create user config directory\") {\n    if mkErr := os.MkdirAll(homeDir, 0o755); mkErr != nil {\n        return fmt.Errorf(\"unwritable HOME; set HOME to a writable dir: %w\", mkErr)\n    }\n    return config.SetUserYamlConfig(key, value)\n}","preventionTips":["Point HOME/USERPROFILE at a writable directory in CI and containers.","Never create a file where the .beads directory belongs.","Keep home writable: check `touch ~/.probe` when troubleshooting.","Avoid read-only bind mounts over $HOME in sandboxes."],"tags":["config","filesystem","directory","permissions"],"backgroundTag":"mkdir-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}