twpayne/chezmoi · error

%s:%d: %w

Error message

%s:%d: %w

What it means

When reading an ignore-file style pattern list (e.g. .chezmoiignore), each line must be a valid relative path. NewUntrustedRelPath rejected the line, and the error is wrapped with the source file and line number so the offending pattern can be located.

Solutions

  1. Fix the offending line at the reported line number to be a plain relative path or glob
  2. Remove absolute paths from the ignore file and use target-relative patterns
  3. Trim stray whitespace/empty entries from pattern lines

Example fix

# before (.chezmoiignore line 3)
/tmp/cache
# after
.cache/tmp
Defensive patterns

Strategy: validation

Validate before calling

for i, line := range strings.Split(ignoreFile, "\n") {
    if _, err := NewUntrustedRelPath(strings.TrimPrefix(line, "!")); err != nil {
        fmt.Printf("invalid pattern at line %d: %v\n", i+1, err)
    }
}

Prevention

When it happens

Trigger: A line in .chezmoiignore (or a pattern set file) is not a valid untrusted relative path — e.g. absolute path, empty line content after '!' prefix handling, or illegal path characters — at sourceAbsPath:lineNumber.

Common situations: Accidentally adding an absolute pattern like "/tmp/foo", patterns with invalid characters, or OS-illegal names (e.g. "con:" on Windows) into .chezmoiignore.

Related errors


AI-assisted analysis of twpayne/chezmoi@f901167e46 (2026-09-01). Data as JSON: /api/errors/482fdc2e6ad0f803. Report an issue: GitHub.

Appendix: source

Thrown at internal/chezmoi/sourcestate.go:1540

	dir, err := sourceRelPath.Dir().TargetRelPath("")
	if err != nil {
		return err
	}
	lineNumber := 0
	for line := range bytes.Lines(data) {
		lineNumber++
		line = commentRx.ReplaceAll(line, nil)
		line = bytes.TrimSpace(line)
		if len(line) == 0 {
			continue
		}
		include := PatternSetInclude
		line, ok := bytes.CutPrefix(line, []byte{'!'})
		if ok {
			include = PatternSetExclude
		}
		if _, err := NewUntrustedRelPath(string(line)); err != nil {
			return fmt.Errorf("%s:%d: %w", sourceAbsPath, lineNumber, err)
		}
		pattern := dir.JoinString(string(line)).String()
		if err := patternSet.Add(pattern, include); err != nil {
			return fmt.Errorf("%s:%d: %w", sourceAbsPath, lineNumber, err)
		}
	}
	return nil
}

// addTemplateData adds all template data in sourceAbsPath to s.
func (s *SourceState) addTemplateData(sourceAbsPath AbsPath) error {
	format, err := FormatFromAbsPath(sourceAbsPath)
	if err != nil {
		return err
	}
	data, err := s.system.ReadFile(sourceAbsPath)
	if err != nil {
		return fmt.Errorf("%s: %w", sourceAbsPath, err)

View on GitHub (pinned to f901167e46)