twpayne/chezmoi · error
%s: %q: %w
Error message
%s: %q: %w
What it means
This wrapped error originates in chezmoi's source state handling (around sourcestate.go:2977, in the script-related error paths) and follows the format '%s: %q: %w': the first %s is the context (usually the target path of the source entry), %q quotes the specific item — commonly a script name or attribute being processed — and %w embeds the underlying error, preserving it for errors.Is/As unwrapping. It is raised when an operation on a source-state entry (such as reading, hashing, or evaluating a script) fails due to an underlying I/O, permission, or parse error. Diagnose it by reading the wrapped error at the end of the message: for example, a 'no such file or directory' means the referenced file is missing from the source state, while a permission error means chezmoi cannot read the entry. Fix the underlying condition (restore the missing file, correct permissions, or repair malformed frontmatter) in ~/.local/share/chezmoi.
Source
Thrown at internal/chezmoi/sourcestate.go:2977
}
}
}
if err := concurrentWalkSourceDir(ctx, s.system, scriptsDirAbsPath, walkFunc); err != nil {
return nil, err
}
return allSourceStateEntries, nil
}
// readVersionFile reads a .chezmoiversion file from sourceAbsPath and returns
// an error if the version is newer that s's version.
func (s *SourceState) readVersionFile(sourceAbsPath AbsPath) error {
data, err := s.system.ReadFile(sourceAbsPath)
if err != nil {
return err
}
version, err := semver.NewVersion(strings.TrimSpace(string(data)))
if err != nil {
return fmt.Errorf("%s: %q: %w", sourceAbsPath, data, err)
}
var zeroVersion semver.Version
if s.version != zeroVersion && s.version.LessThan(*version) {
return &TooOldError{
Have: s.version,
Need: *version,
}
}
return nil
}
// sourceStateEntry returns a new SourceStateEntry based on actualStateEntry.
func (s *SourceState) sourceStateEntry(
actualStateEntry ActualStateEntry,
destAbsPath AbsPath,
fileInfo fs.FileInfo,
parentSourceRelPath SourceRelPath,
targetRelPath RelPath,View on GitHub (pinned to f901167e46)
Solutions
- Make the file contain exactly one valid semantic version string (e.g. 2.1.0), trimmed of extra text
- Remove surrounding prose/quotes/constraint operators; use a bare MAJOR.MINOR.PATCH
- Include the patch segment — '1.2' is invalid, '1.2.0' is valid
Example fix
// before (version file contents) 1.2 // after 2.1.0
Defensive patterns
Strategy: validation
Validate before calling
// validate the version file is strict semver before relying on it
re := regexp.MustCompile(`^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$`)
data, _ := os.ReadFile(versionFile)
v := strings.TrimSpace(string(data))
if !re.MatchString(v) { return fmt.Errorf("%s: not strict semver: %q", versionFile, v) } Type guard
func isStrictSemver(s string) bool {
_, err := semver.NewVersion(strings.TrimSpace(s))
return err == nil
} Try / catch
// catch and surface the offending contents
version, err := semver.NewVersion(strings.TrimSpace(string(data)))
if err != nil {
return fmt.Errorf("version file %s contains invalid semver %q: %w", path, data, err)
} Prevention
- Keep version files to exactly one bare MAJOR.MINOR.PATCH line
- Never hand-edit version files to include constraints or prose
- Add CI validation that semver.NewVersion parses every version file
When it happens
Trigger: A source-state file (e.g. a .chezmoiversion-style file read here) whose trimmed contents fail semver parsing — empty file, plain text, 'v' prefix issues, or multiple lines/whitespace oddities that TrimSpace doesn't fix.
Common situations: Hand-edited version files containing notes or '>=1.2.3' constraints instead of a bare semver string; empty file committed by accident; version written as '1.2' (missing patch) which is not valid strict semver.
Related errors
- empty directory name
- empty filename
- %s: parse error
- %s: unknown entry type
- %s: cannot add chezmoi's config file to chezmoi, use a confi
AI-assisted analysis of twpayne/chezmoi@f901167e46 (2026-09-01).
Data as JSON: /api/errors/389f9279494d8afa.
Report an issue: GitHub.