{"record":{"id":"734f8ee5d09d1f0b","repo":"twpayne/chezmoi","slug":"s-cannot-add-chezmoi-file-to-chezmoi-s-is-prot","errorCode":null,"errorMessage":"%s: cannot add chezmoi file to chezmoi (%s is protected)","messagePattern":"(.+?): cannot add chezmoi file to chezmoi \\((.+?) is protected\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":433,"sourceCode":"\t\tn++\n\t}\n\tdestAbsPaths = destAbsPaths[:n]\n\n\t// Check for protected paths.\n\tfor _, destAbsPath := range destAbsPaths {\n\t\tif destAbsPath == options.ConfigFileAbsPath {\n\t\t\tformat := \"%s: cannot add chezmoi's config file to chezmoi, use a config file template instead\"\n\t\t\treturn fmt.Errorf(format, destAbsPath)\n\t\t}\n\t}\n\tfor _, destAbsPath := range destAbsPaths {\n\t\tfor _, protectedAbsPath := range options.ProtectedAbsPaths {\n\t\t\tif protectedAbsPath.IsEmpty() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif destAbsPath.HasDirPrefix(protectedAbsPath) {\n\t\t\t\tformat := \"%s: cannot add chezmoi file to chezmoi (%s is protected)\"\n\t\t\t\treturn fmt.Errorf(format, destAbsPath, protectedAbsPath)\n\t\t\t}\n\t\t}\n\t}\n\n\ttype sourceUpdate struct {\n\t\tdestAbsPath    AbsPath\n\t\tentryState     *EntryState\n\t\tsourceRelPaths []SourceRelPath\n\t}\n\n\tsourceUpdates := make([]sourceUpdate, 0, len(destAbsPaths))\n\tnewSourceStateEntries := make(map[SourceRelPath]SourceStateEntry)\n\tnewSourceStateEntriesByTargetRelPath := make(map[RelPath]SourceStateEntry)\n\tnonEmptyDirs := chezmoiset.New[SourceRelPath]()\n\texternalDirRelPaths := chezmoiset.New[RelPath]()\n\tdirRenames := make(map[AbsPath]AbsPath)\nDEST_ABS_PATH:\n\tfor _, destAbsPath := range destAbsPaths {","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L415-L451","documentation":"chezmoi protects a set of directories (options.ProtectedAbsPaths, e.g. the source directory itself and other internal state dirs). If a path being added lies under any protected directory, the add is rejected to prevent chezmoi from managing files inside its own state.","triggerScenarios":"'chezmoi add' (or programmatic add via SourceState update) on a destAbsPath with HasDirPrefix(protectedAbsPath) true for any non-empty protected path, e.g. adding files under ~/.local/share/chezmoi.","commonSituations":"Users add their entire home or .config tree with wildcards/recurse and accidentally include the source directory or other protected state; scripts using 'chezmoi add ~/.local/share/chezmoi'.","solutions":["Remove the protected path from the add list; use 'chezmoi add' on specific files instead of whole directories.","Use 'chezmoi ignore' or .chezmoiignore patterns to keep protected paths out of bulk adds.","If you intended to edit source files, edit them directly in the source directory rather than adding them."],"exampleFix":"// before (fails)\n$ chezmoi add -r ~/.config\n// after\n$ chezmoi add ~/.config/git/config ~/.config/starship.toml","handlingStrategy":"validation","validationCode":"src=$(chezmoi source-path)\ncase \"$1\" in\n  \"$src\"|\"$src\"/*) echo \"path is inside the protected source dir\" >&2; exit 1;;\nesac","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add specific files, not whole directories","Use .chezmoiignore to exclude internal state paths","Never 'chezmoi add -r' your entire home"],"tags":["chezmoi","protected-path","recursive-add"],"backgroundTag":"protected-path-rejected","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}