{"record":{"id":"7dd0d8f5adf45857","repo":"gastownhall/beads","slug":"failed-to-read-user-config-yaml-w","errorCode":null,"errorMessage":"failed to read user config.yaml: %w","messagePattern":"failed to read user config\\.yaml: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/yaml_config.go","lineNumber":471,"sourceCode":"\tif err != nil {\n\t\treturn false\n\t}\n\treturn shown\n}\n\nfunc UnsetUserYamlConfig(key string) error {\n\tconfigPath, err := UserConfigYamlPath()\n\tif err != nil {\n\t\treturn err\n\t}\n\tnormalizedKey := normalizeYamlKey(key)\n\n\tcontent, err := os.ReadFile(configPath) //nolint:gosec // configPath is a validated absolute user config path\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"failed to read user config.yaml: %w\", err)\n\t}\n\n\tnewContent := commentOutYamlKey(string(content), normalizedKey)\n\n\t// Preserve the owner-private 0600 posture every other user-global writer\n\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}","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/config/yaml_config.go#L453-L489","documentation":"UnsetUserYamlConfig reads the user-level config.yaml (path from UserConfigYamlPath) to comment out the given key. If ReadFile fails with anything other than not-exists (which is treated as success/no-op), it wraps the error as 'failed to read user config.yaml'.","triggerScenarios":"Calling UnsetUserYamlConfig(key) when ~/.beads/config.yaml (or the platform equivalent) exists but cannot be read: permission denied, path is a directory, or a transient I/O error. Not-exist returns nil instead.","commonSituations":"Config file owned by root after running bd with sudo; config.yaml replaced by a directory; antivirus/backup tools locking the file on Windows.","solutions":["Fix file permissions: chmod 600 ~/.beads/config.yaml and ensure it is owned by the current user (chown $USER).","If config.yaml is a directory, rename/remove it and recreate as a file.","Check the wrapped %w cause for the underlying errno and resolve it (disk, lock, AV scanner).","If the key was never set, no action needed — a missing file is already treated as success."],"exampleFix":"// before\nsudo bd config set metrics.enabled true   # creates root-owned config\nbd config unset metrics.enabled            // read fails EACCES\n// after\nsudo chown $USER ~/.beads/config.yaml\nchmod 600 ~/.beads/config.yaml\nbd config unset metrics.enabled","handlingStrategy":"try-catch","validationCode":"info, err := os.Stat(userConfigPath)\nif err == nil {\n    if info.IsDir() { return errors.New(\"user config.yaml is a directory\") }\n    if err := unix.Access(userConfigPath, unix.R_OK); err != nil {\n        return fmt.Errorf(\"user config.yaml unreadable: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"err := config.UnsetUserYamlConfig(key)\nvar pe *fs.PathError\nif errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrPermission) {\n    // advise: chown $USER ~/.beads/config.yaml && chmod 600 ...\n    return adviseOwnershipFix(pe.Path)\n}","preventionTips":["Never run bd config commands under sudo; it creates root-owned user config.","Keep ~/.beads/config.yaml at mode 600 owned by the current user.","Watch for AV/backup tools locking files on Windows.","Treat not-found as success — only real read failures need fixing."],"tags":["config","filesystem","permissions"],"backgroundTag":"config-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}