twpayne/chezmoi · error
%s: cannot add chezmoi file to chezmoi (%s is protected)
Error message
%s: cannot add chezmoi file to chezmoi (%s is protected)
What it means
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.
Source
Thrown at internal/chezmoi/sourcestate.go:433
n++
}
destAbsPaths = destAbsPaths[:n]
// Check for protected paths.
for _, destAbsPath := range destAbsPaths {
if destAbsPath == options.ConfigFileAbsPath {
format := "%s: cannot add chezmoi's config file to chezmoi, use a config file template instead"
return fmt.Errorf(format, destAbsPath)
}
}
for _, destAbsPath := range destAbsPaths {
for _, protectedAbsPath := range options.ProtectedAbsPaths {
if protectedAbsPath.IsEmpty() {
continue
}
if destAbsPath.HasDirPrefix(protectedAbsPath) {
format := "%s: cannot add chezmoi file to chezmoi (%s is protected)"
return fmt.Errorf(format, destAbsPath, protectedAbsPath)
}
}
}
type sourceUpdate struct {
destAbsPath AbsPath
entryState *EntryState
sourceRelPaths []SourceRelPath
}
sourceUpdates := make([]sourceUpdate, 0, len(destAbsPaths))
newSourceStateEntries := make(map[SourceRelPath]SourceStateEntry)
newSourceStateEntriesByTargetRelPath := make(map[RelPath]SourceStateEntry)
nonEmptyDirs := chezmoiset.New[SourceRelPath]()
externalDirRelPaths := chezmoiset.New[RelPath]()
dirRenames := make(map[AbsPath]AbsPath)
DEST_ABS_PATH:
for _, destAbsPath := range destAbsPaths {View on GitHub (pinned to f901167e46)
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.
Example fix
// before (fails) $ chezmoi add -r ~/.config // after $ chezmoi add ~/.config/git/config ~/.config/starship.toml
Defensive patterns
Strategy: validation
Validate before calling
src=$(chezmoi source-path) case "$1" in "$src"|"$src"/*) echo "path is inside the protected source dir" >&2; exit 1;; esac
Prevention
- Add specific files, not whole directories
- Use .chezmoiignore to exclude internal state paths
- Never 'chezmoi add -r' your entire home
When it happens
Trigger: '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.
Common situations: 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'.
Related errors
- %s: cannot add chezmoi's config file to chezmoi, use a confi
- %s: parent directory not in source state
- %s: not a directory
- %s: %w
- %s: empty path
AI-assisted analysis of twpayne/chezmoi@f901167e46 (2026-09-01).
Data as JSON: /api/errors/734f8ee5d09d1f0b.
Report an issue: GitHub.