{"record":{"id":"c356c62dd94053ed","repo":"twpayne/chezmoi","slug":"s-not-allowed-in-s-directory","errorCode":null,"errorMessage":"%s: not allowed in %s directory","messagePattern":"(.+?): not allowed in (.+?) directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":1490,"sourceCode":"\t\ts.externals[targetRelPath] = append(s.externals[targetRelPath], &external)\n\t}\n\treturn nil\n}\n\n// addExternalDir adds all externals in externalsDirAbsPath to s.\nfunc (s *SourceState) addExternalDir(ctx context.Context, externalsDirAbsPath AbsPath) error {\n\twalkFunc := func(ctx context.Context, externalAbsPath AbsPath, fileInfo fs.FileInfo, err error) error {\n\t\tif externalAbsPath == externalsDirAbsPath {\n\t\t\treturn nil\n\t\t}\n\t\tif err == nil && fileInfo.Mode().Type() == fs.ModeSymlink {\n\t\t\tfileInfo, err = s.system.Stat(externalAbsPath)\n\t\t}\n\t\tswitch {\n\t\tcase err != nil:\n\t\t\treturn err\n\t\tcase strings.HasPrefix(fileInfo.Name(), Prefix):\n\t\t\treturn fmt.Errorf(\"%s: not allowed in %s directory\", externalAbsPath, externalsDirName)\n\t\tcase strings.HasPrefix(fileInfo.Name(), ignorePrefix):\n\t\t\tif fileInfo.IsDir() {\n\t\t\t\treturn fs.SkipDir\n\t\t\t}\n\t\t\treturn nil\n\t\tcase fileInfo.Mode().IsRegular():\n\t\t\tparentAbsPath, _ := externalAbsPath.Split()\n\t\t\treturn s.addExternal(externalAbsPath, parentAbsPath.Dir())\n\t\tcase fileInfo.IsDir():\n\t\t\treturn nil\n\t\tdefault:\n\t\t\treturn &UnsupportedFileTypeError{\n\t\t\t\tabsPath: externalAbsPath,\n\t\t\t\tmode:    fileInfo.Mode(),\n\t\t\t}\n\t\t}\n\t}\n\treturn concurrentWalkSourceDir(ctx, s.system, externalsDirAbsPath, walkFunc)","sourceCodeStart":1472,"sourceCodeEnd":1508,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L1472-L1508","documentation":"Files inside the .chezmoiexternal source directory whose names begin with chezmoi's reserved Prefix (\".\") are not permitted. The walk over the externals directory stat()s each entry and rejects entries named like internal chezmoi files, since they could be confused with chezmoi control files.","triggerScenarios":"Placing a file or directory whose name starts with \".\" (the Prefix) inside the .chezmoiexternal.d directory while chezmoi walks the externals directory (sourcestate.go:1490).","commonSituations":"Hidden files (e.g. .DS_Store, .gitignore) extracted or committed inside .chezmoiexternal.d, or accidentally copying dotfiles into the externals directory.","solutions":["Remove or rename the dot-prefixed file inside the .chezmoiexternal.d directory","Add the file to .gitignore so it never enters the source state","If it must be tracked, rename it without a leading dot"],"exampleFix":"# before\n.chezmoiexternal.d/\n  .DS_Store\n  browser.toml\n# after (delete .DS_Store)\n.chezmoiexternal.d/\n  browser.toml","handlingStrategy":"validation","validationCode":"for _, f := range entriesOfExternalsDir {\n    if strings.HasPrefix(f, \".\") {\n        fmt.Printf(\"remove dot-prefixed file %s from .chezmoiexternal.d\\n\", f)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never place dotfiles in .chezmoiexternal.d","Add .DS_Store etc. to .gitignore"],"tags":["naming","externals","source-state"],"backgroundTag":"reserved-filename-in-source-dir","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}