twpayne/chezmoi · error

%s: path not found in %s

Error message

%s: path not found in %s

What it means

After downloading an archive and walking it to find the entry matching external.ArchivePath, no entry matched, so sourceStateEntry stays nil and chezmoi raises 'path not found in <url>'. It means the configured archive path does not exist inside the downloaded archive.

Source

Thrown at internal/chezmoi/sourcestate.go:2739

				sourceAttr: SourceAttr{
					External: true,
				},
			}
			sourceStateEntry = &SourceStateFile{
				attr:             fileAttr,
				origin:           external,
				sourceRelPath:    sourceRelPath,
				targetStateEntry: targetStateEntry,
			}
			return fs.SkipAll
		default:
			return fmt.Errorf("%s: unsupported mode %o", name, fileInfo.Mode()&fs.ModeType)
		}
	}); err != nil {
		return nil, err
	}
	if sourceStateEntry == nil {
		return nil, fmt.Errorf("%s: path not found in %s", external.ArchivePath, urlStr)
	}

	return s.populateImplicitParentDirs(externalRelPath, external, map[RelPath][]SourceStateEntry{
		externalRelPath: {sourceStateEntry},
	}), nil
}

// readExternalDir returns all source state entries in an external_ dir.
func (s *SourceState) readExternalDir(
	rootSourceAbsPath AbsPath,
	rootSourceRelPath SourceRelPath,
	rootTargetRelPath RelPath,
) (map[RelPath][]SourceStateEntry, error) {
	sourceStateEntries := make(map[RelPath][]SourceStateEntry)
	walkFunc := func(absPath AbsPath, fileInfo fs.FileInfo, err error) error {
		switch {
		case err != nil:
			return err

View on GitHub (pinned to f901167e46)

Solutions

  1. List the archive contents (tar -tzf / unzip -l <url-download>) and correct archivePath to an entry that actually exists
  2. Check for typos and trailing-slash/case mismatches in the archivePath value
  3. Pin the URL/version so the archive layout stays consistent, or update config after upstream layout changes

Example fix

// before
[[external]]
  url = "https://github.com/x/y/archive/v2.tar.gz"
  archivePath = "y-2/config/old-name"  # renamed upstream
// after
  archivePath = "y-2/config/new-name"
Defensive patterns

Strategy: validation

Validate before calling

// verify archivePath exists before configuring:
url=https://github.com/x/y/archive/v2.tar.gz
curl -sL "$url" -o /tmp/a.tgz && tar -tzf /tmp/a.tgz | grep 'y-2/config/'

Try / catch

// wrap apply and report which external failed
if err := chezmoiApply(); err != nil {
  if strings.Contains(err.Error(), "path not found in") {
    log.Fatalf("external archivePath mismatch: %v — list archive contents and fix archivePath", err)
  }
  return err
}

Prevention

When it happens

Trigger: .chezmoiexternal entry with archivePath (and often exactArchivePath) referencing a file/directory that does not exist in the archive at the given URL; path spelling, case, or stripComponents mismatch.

Common situations: Upstream project renamed or moved a file inside its release tarball; typo in archivePath; archive layout changed between versions (e.g. subdir added); pinning an old URL whose layout differs from your config.

Related errors


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