{"record":{"id":"b81eeb95b92dbf6a","repo":"twpayne/chezmoi","slug":"s-w-b81eeb","errorCode":null,"errorMessage":"%s: %w","messagePattern":"%s: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":1441,"sourceCode":"// addExternal adds external source entries to s.\nfunc (s *SourceState) addExternal(sourceAbsPath, parentAbsPath AbsPath) error {\n\tparentRelPath, err := parentAbsPath.TrimDirPrefix(s.sourceDirAbsPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tparentSourceRelPath := NewSourceRelDirPath(parentRelPath.String())\n\tparentTargetSourceRelPath, err := parentSourceRelPath.TargetRelPath(s.encryption.EncryptedSuffix())\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tformat, err := FormatFromAbsPath(sourceAbsPath.TrimSuffix(TemplateSuffix))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdata, err := s.executeTemplate(sourceAbsPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s: %w\", sourceAbsPath, err)\n\t}\n\texternals := make(map[string]External)\n\tif err := format.Unmarshal(data, &externals); err != nil {\n\t\treturn fmt.Errorf(\"%s: %w\", sourceAbsPath, err)\n\t}\n\ts.mutex.Lock()\n\tdefer s.mutex.Unlock()\n\tfor targetPath, external := range externals {\n\t\tif external.TargetPath != \"\" {\n\t\t\ttargetPath = external.TargetPath\n\t\t}\n\t\tif targetPath == \"\" {\n\t\t\treturn fmt.Errorf(\"%s: empty path\", sourceAbsPath)\n\t\t}\n\n\t\texternalPath := path.Clean(targetPath)\n\t\tif strings.HasPrefix(externalPath, \"/\") || filepath.IsAbs(externalPath) {\n\t\t\treturn fmt.Errorf(\"%s: %s: path is not relative\", sourceAbsPath, targetPath)","sourceCodeStart":1423,"sourceCodeEnd":1459,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L1423-L1459","documentation":"When reading a .chezmoiexternal file (or external entry source), chezmoi first executes it as a template, then wraps any template execution error with the source file path for context. The underlying %w error is the template failure (syntax error, missing variable, failing function).","triggerScenarios":"A .chezmoiexternal.toml/.json/.yaml containing template syntax ({{ ... }}) that fails to execute, e.g. referencing undefined .chezmoi* variables or calling a template function with bad args.","commonSituations":"Template typos like {{ .chezmoi.hostname }} in files that don't get template context; copy-pasted template snippets into externals; version change removing a template function.","solutions":["Run 'chezmoi execute-template < <file>' or inspect the wrapped error message to find the failing template expression and fix it.","Remove unnecessary {{ }} constructs from the external file (static content doesn't need templating).","Verify template variables exist for your environment ('chezmoi data')."],"exampleFix":"// before (.chezmoiexternal.toml.tmpl)\nurl = \"https://example.com/{{ .undefinedVar }}\"\n// after\nurl = \"https://example.com/{{ .chezmoi.hostname }}/asset\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := sourceState.readExternal(...)\nvar pathErr *fmt.WrapError // or match on prefix\nif err != nil {\n  if strings.Contains(err.Error(), \": \") && templateFailed(err) {\n    // log file path from prefix, surface inner template error to user\n  }\n}","preventionTips":["Test external templates with 'chezmoi execute-template'","Only template files that need dynamic values","Pin template functions you rely on to chezmoi versions"],"tags":["chezmoi","template","external"],"backgroundTag":"template-execution-failed","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}