{"record":{"id":"494015b289392098","repo":"helm/helm","slug":"error-evaluating-symlink-s-w","errorCode":null,"errorMessage":"error evaluating symlink %s: %w","messagePattern":"error evaluating symlink (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sympath/walk.go","lineNumber":72,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnames, err := f.Readdirnames(-1)\n\tf.Close()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsort.Strings(names)\n\treturn names, nil\n}\n\n// symwalk recursively descends path, calling walkFn.\nfunc symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {\n\t// Recursively walk symlinked directories.\n\tif IsSymlink(info) {\n\t\tresolved, err := filepath.EvalSymlinks(path)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error evaluating symlink %s: %w\", path, err)\n\t\t}\n\t\t// This log message is to highlight a symlink that is being used within a chart, symlinks can be used for nefarious reasons.\n\t\tslog.Info(\"found symbolic link in path. Contents of linked file included and used\", \"path\", path, \"resolved\", resolved)\n\t\tif info, err = os.Lstat(resolved); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := symwalk(path, info, walkFn); err != nil && !errors.Is(err, filepath.SkipDir) {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n\n\tif err := walkFn(path, info, nil); err != nil {\n\t\treturn err\n\t}\n\n\tif !info.IsDir() {\n\t\treturn nil","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/helm/helm/blob/2a29f1770b62844b27197d2507377361d45ad7c0/internal/sympath/walk.go#L54-L90","documentation":"internal/sympath implements a symlink-following replacement for filepath.Walk, and Helm uses it when loading a chart from a directory tree. This error fires when the walker hits a symlink and filepath.EvalSymlinks cannot resolve it; the wrapped error is the OS reason (target missing, permission denied on a path component, or a symlink loop). Because chart loading goes through this walker, a single broken symlink anywhere under the chart root aborts the whole load. Note that Helm deliberately follows chart symlinks (it logs an info message about it), so it does not skip bad ones.","triggerScenarios":"Loading a chart from a directory (helm install ./mychart, helm package ./mychart, SDK chart load with a local path) where the tree contains a dangling symlink, a symlink into a directory the process cannot traverse, or two symlinks pointing at each other. The tar format preserves symlinks, so an unpacked .tgz can carry a link that was valid on the packager's machine but not on yours.","commonSituations":"Charts checked into git with symlinks that resolve only on the original author's machine (e.g., into /etc or a home dir); unpacked chart archives containing absolute symlinks; build pipelines copying node_modules-style or shared-config layouts into a chart; CI runners with restricted directory permissions; accidental symlink cycles created while reorganizing templates.","solutions":["List the dangling links in the chart: find <chart-dir> -xtype l (or ls -la on the path named in the error)","Fix or delete each broken symlink reported in the error message","If the link is intentional, make it relative to the chart root and verify it resolves on the machine running Helm","Re-create the distribution artifact with helm package from the repaired directory"],"exampleFix":"# before: templates/config.yaml -> /etc/myapp/config.yaml (target absent on this host)\nln -sfn ../../files/config.yaml mychart/templates/config.yaml\n\n# after\nhelm package mychart  # succeeds","handlingStrategy":"validation","validationCode":"// before loading or packaging a chart directory, scan for unresolvable symlinks\nerr := filepath.WalkDir(chartDir, func(p string, d fs.DirEntry, err error) error {\n\tif err != nil {\n\t\treturn err\n\t}\n\tif d.Type()&fs.ModeSymlink != 0 {\n\t\tif _, err := filepath.EvalSymlinks(p); err != nil {\n\t\t\treturn fmt.Errorf(\"broken symlink %s: %w\", p, err)\n\t\t}\n\t}\n\treturn nil\n})","typeGuard":null,"tryCatchPattern":"if err := loader.Load(chartDir); err != nil {\n\tvar linkErr *fs.PathError\n\tif errors.As(err, &linkErr) && strings.Contains(err.Error(), \"error evaluating symlink\") {\n\t\t// point the user at the broken symlink named in the message\n\t}\n}","preventionTips":["Run find <chart-dir> -xtype l in CI to fail on dangling symlinks before Helm sees them","Prefer chart tarballs (helm package output) produced on the same tree you validated","Use only symlinks with targets relative to the chart root","Never copy absolute symlinks from local dev setups into chart directories"],"tags":["filesystem","chart","symlink","packaging"],"backgroundTag":null,"analyzedSha":"2a29f1770b62844b27197d2507377361d45ad7c0","analyzedAt":"2026-08-15T22:02:47.490Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}