{"record":{"id":"054c6cdf0d254049","repo":"slimtoolkit/slim","slug":"findsymlinks-could-not-convert-fileinfo-to-stat","errorCode":null,"errorMessage":"findSymlinks - could not convert fileInfo to Stat_t for %s","messagePattern":"findSymlinks - could not convert fileInfo to Stat_t for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/app/sensor/artifact/artifact.go","lineNumber":3446,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif err != nil {\n\t\t\t\tlog.Debugf(\"findSymlinks: error accessing %q: %v\\n\", fullName, err)\n\t\t\t\t//just ignore the error and keep going\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tif fileInfo.Sys() == nil {\n\t\t\t\tlog.Debugf(\"findSymlinks: fileInfo.Sys() is nil (ignoring)\")\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tsysStatInfo, ok := fileInfo.Sys().(*syscall.Stat_t)\n\t\t\tif !ok {\n\t\t\t\treturn fmt.Errorf(\"findSymlinks - could not convert fileInfo to Stat_t for %s\", fullName)\n\t\t\t}\n\n\t\t\tif _, ok := devices[uint64(sysStatInfo.Dev)]; !ok {\n\t\t\t\tlog.Debugf(\"findSymlinks: ignoring %v (by device id - %v)\", fullName, sysStatInfo.Dev)\n\t\t\t\t//NOTE:\n\t\t\t\t//don't return filepath.SkipDir for everything\n\t\t\t\t//because we might still need other files in the dir\n\t\t\t\t//return filepath.SkipDir\n\t\t\t\t//example: \"/etc/hostname\" Docker mounts from another device\n\t\t\t\t//NOTE:\n\t\t\t\t//can move the checks for /dev, /sys and /proc here too\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tif fileInfo.Mode()&os.ModeSymlink != 0 {\n\t\t\t\tcheckPathSymlinks(fullName)\n\n\t\t\t\tif info, err := getFileSysStats(fullName); err == nil {","sourceCodeStart":3428,"sourceCodeEnd":3464,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/app/sensor/artifact/artifact.go#L3428-L3464","documentation":"findSymlinks walks the filesystem collecting symlinks and filters entries by the device they live on. It asserts that each dirent's Sys() value is a *syscall.Stat_t; on Linux this always succeeds, but on other platforms Sys() returns a different type. When the assertion fails the walk aborts with this error, stopping symlink discovery entirely.","triggerScenarios":"Running the artifact scanner on a non-Linux platform (or a filesystem layer whose os.FileInfo.Sys() is not *syscall.Stat_t) while findSymlinks processes a directory entry.","commonSituations":"Cross-compiling or porting the sensor to darwin/Windows where FileInfo.Sys() carries a different stat type; FUSE or exotic filesystems returning nil/alternative Sys() payloads.","solutions":["Build/run the sensor only on Linux targets where Sys() is guaranteed to be *syscall.Stat_t","Mirror the nil-Sys() handling above: log and skip entries whose Sys() cannot be converted instead of failing the whole walk","Use a portable stat conversion (e.g. fileInfo.Sys() with platform-specific assertions per GOOS)"],"exampleFix":"// before\nsysStatInfo, ok := fileInfo.Sys().(*syscall.Stat_t)\nif !ok {\n\treturn fmt.Errorf(\"findSymlinks - could not convert fileInfo to Stat_t for %s\", fullName)\n}\n// after\nsysStatInfo, ok := fileInfo.Sys().(*syscall.Stat_t)\nif !ok {\n\tlog.Debugf(\"findSymlinks: cannot convert to Stat_t (ignoring): %s\", fullName)\n\treturn nil\n}","handlingStrategy":"type-guard","validationCode":"if fi, err := os.Lstat(path); err == nil {\n\tif _, ok := fi.Sys().(*syscall.Stat_t); !ok {\n\t\tlog.Printf(\"non-Stat_t filesystem: %s\", path)\n\t}\n}","typeGuard":"func asStatT(fi os.FileInfo) (*syscall.Stat_t, bool) {\n\ts, ok := fi.Sys().(*syscall.Stat_t)\n\treturn s, ok\n}","tryCatchPattern":"if err := walkErr; err != nil {\n\tvar convErr *fmt.Errorf\n\tif strings.Contains(err.Error(), \"could not convert fileInfo to Stat_t\") {\n\t\t// degrade gracefully: skip symlink device filtering\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["Target Linux-only builds for this code path (build tags //go:build linux)","Treat Stat_t conversion failure as skip-and-log, not fatal","Add unit tests with fake FileInfo implementations to assert skip behavior"],"tags":["go","filesystem","type-assertion","cross-platform"],"backgroundTag":"fileinfo-sys-type-assertion-failed","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}