{"record":{"id":"0caf636887dc2169","repo":"gastownhall/beads","slug":"failed-to-write-config-yaml-w-0caf63","errorCode":null,"errorMessage":"failed to write config.yaml: %w","messagePattern":"failed to write config\\.yaml: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/yaml_config.go","lineNumber":526,"sourceCode":"\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\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read config.yaml: %w\", err)\n\t}\n\n\t// Update or add the key\n\tnewContent, err := updateYamlKey(string(content), normalizedKey, value)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Write back\n\tif err := os.WriteFile(configPath, []byte(newContent), 0600); err != nil { //nolint:gosec // configPath is validated\n\t\treturn fmt.Errorf(\"failed to write config.yaml: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// GetYamlConfig gets a configuration value from config.yaml.\n// Returns empty string if key is not found or is commented out.\n// Keys are normalized to their canonical yaml format (e.g., sync.branch -> sync-branch).\nfunc GetYamlConfig(key string) string {\n\tif v == nil {\n\t\treturn \"\"\n\t}\n\tnormalizedKey := normalizeYamlKey(key)\n\treturn v.GetString(normalizedKey)\n}\n\n// UnsetYamlConfig removes a configuration value from the project's config.yaml file.\n// The key line is commented out (prefixed with \"# \") to preserve it as documentation.","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/config/yaml_config.go#L508-L544","documentation":"setYamlConfigAtPath wraps any os.WriteFile failure after successfully computing the updated YAML content. The file was read fine but writing the merged content back failed; the OS-level cause is preserved via %w. bd throws it because a failed write would silently drop the config change.","triggerScenarios":"Calling SetYamlConfig / SetYamlConfigInDir / SetUserYamlConfig when the config.yaml file or its containing directory is read-only, the disk is full, the path became a directory, or the process lacks write permission (mode 0600 write by a different user).","commonSituations":"Running bd as a non-root user against a root-owned config.yaml; read-only mount or checked-out repo with read-only .beads/config.yaml; disk quota exceeded in CI containers.","solutions":["Inspect the wrapped cause: 'permission denied' -> chmod/chown config.yaml so the current user can write (chmod u+w .beads/config.yaml)","Free disk space or resolve quota if the cause is ENOSPC","Ensure config.yaml is a regular file, not a directory or broken symlink","Re-run the command with the appropriate user/credentials (e.g., not sudo-stripped ownership)"],"exampleFix":"// before (fails: read-only file)\n$ bd config set dolt.shared-server false\nfailed to write config.yaml: ... permission denied\n// after\n$ chmod u+w .beads/config.yaml\n$ bd config set dolt.shared-server false","handlingStrategy":"try-catch","validationCode":"fi, err := os.Stat(configPath)\nif err != nil || !fi.Mode().IsRegular() {\n    return fmt.Errorf(\"config.yaml not writable-regular: %s\", configPath)\n}\nif err := syscall.Access(configPath, syscall.O_RDWR); err != nil {\n    return fmt.Errorf(\"no write permission on %s\", configPath)\n}","typeGuard":"func configWritable(path string) bool {\n    f, err := os.OpenFile(path, os.O_WRONLY, 0)\n    if err != nil { return false }\n    f.Close()\n    return true\n}","tryCatchPattern":"if err := SetYamlConfig(key, value); err != nil {\n    if errors.Is(err, os.ErrPermission) { /* fix perms */ }\n    if errors.Is(err, syscall.ENOSPC) { /* free disk */ }\n    return err\n}","preventionTips":["Keep config.yaml owned by the user running bd (avoid sudo-induced ownership drift)","Monitor disk space in CI environments before config writes","Never replace config.yaml with a directory or read-only artifact in build pipelines"],"tags":["config","file-io","permissions","go"],"backgroundTag":"config-file-write-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}