twpayne/chezmoi · error
%s: %w
Error message
%s: %w
What it means
When applying a modify-script (ModifyDirWithCmd / script that mutates a directory), chezmoi runs the command via system.RunCmd and wraps any failure as '<path>: <underlying error>'. The wrapped error comes from the command's non-zero exit or execution failure.
Source
Thrown at internal/chezmoi/targetstateentry.go:103
Name RelPath `json:"name" yaml:"name"`
RunAt time.Time `json:"runAt" yaml:"runAt"`
}
// Apply updates actualStateEntry to match t.
func (t *TargetStateModifyDirWithCmd) Apply(
system System,
persistentState PersistentState,
actualStateEntry ActualStateEntry,
) (bool, error) {
if _, ok := actualStateEntry.(*ActualStateDir); !ok {
if err := actualStateEntry.Remove(system); err != nil {
return false, err
}
}
runAt := time.Now().UTC()
if err := system.RunCmd(t.cmdFunc()); err != nil {
return false, fmt.Errorf("%s: %w", actualStateEntry.Path(), err)
}
modifyDirWithCmdStateKey := []byte(actualStateEntry.Path().String())
if err := PersistentStateSet(
persistentState, GitRepoExternalStateBucket, modifyDirWithCmdStateKey, &ModifyDirWithCmdState{
Name: actualStateEntry.Path(),
RunAt: runAt,
},
); err != nil {
return false, err
}
return true, nil
}
// EntryState returns t's entry state.
func (t *TargetStateModifyDirWithCmd) EntryState(umask fs.FileMode) (*EntryState, error) {
return &EntryState{View on GitHub (pinned to f901167e46)
Solutions
- Read the wrapped underlying error and fix the modify script itself (run it manually to reproduce)
- Ensure the script is executable and its interpreter exists on the target machine
- Make the script idempotent and tolerant of missing tooling/network (check command availability first)
Example fix
// before (modify script) git -C $CHEZMOI_WORKING_TREE pull --rebase // after #!/bin/sh command -v git >/dev/null || exit 0 git -C "$CHEZMOI_WORKING_TREE" pull --rebase || true
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: run the modify command yourself before apply
cmd := exec.Command("sh", "-c", scriptContents)
if out, err := cmd.CombinedOutput(); err != nil {
return fmt.Errorf("modify script would fail: %v: %s", err, out)
} Try / catch
if err := t.Apply(system, persistentState); err != nil {
var wrapped = err // formatted as "<path>: <cause>"
log.Printf("apply failed on %s: %v — run the modify script manually to debug", path, wrapped)
return wrapped
} Prevention
- Make modify scripts idempotent and non-fatal where safe
- Guard on tool availability (command -v) inside modify scripts
- Test modify scripts on a clean machine to catch missing dependencies
- Ensure scripts are executable and use absolute interpreter paths
When it happens
Trigger: A modify_ script (runCmd on a directory-type target, e.g. git repo or managed-by-tool dir) exits non-zero or cannot be executed during `chezmoi apply`.
Common situations: Modify script depends on a tool not installed on the new machine; script fails due to network/auth when refreshing external content; script not executable or has a bug that only manifests under apply.
Related errors
- %s: cannot add chezmoi's config file to chezmoi, use a confi
- %s: cannot add chezmoi file to chezmoi (%s is protected)
- %s: parent directory not in source state
- %s: not a directory
- %s: %w
AI-assisted analysis of twpayne/chezmoi@f901167e46 (2026-09-01).
Data as JSON: /api/errors/a8efc5f5f1c3d479.
Report an issue: GitHub.