{"record":{"id":"3a1d77ba44ec4447","repo":"slimtoolkit/slim","slug":"not-a-directory","errorCode":null,"errorMessage":"not a directory","messagePattern":"not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/fsutil/fsutil.go","lineNumber":1442,"sourceCode":"\t\t\tlog.Errorf(\"fsutil.ArchiveFiles: bad file - %s\", fname)\n\t\t\treturn fmt.Errorf(\"bad file - %s\", fname)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc ArchiveDir(afname string,\n\td2aname string,\n\ttrimPrefix string,\n\taddPrefix string) error {\n\tdirInfo, err := os.Stat(d2aname)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !dirInfo.IsDir() {\n\t\treturn fmt.Errorf(\"not a directory\")\n\t}\n\n\ttf, err := os.Create(afname)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer close(tf)\n\n\ttw := tar.NewWriter(tf)\n\tdefer close(tw)\n\n\tonFSObject := func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\tlog.Errorf(\"fsutil.ArchiveDir.onFSObject: path=%q err=%q\", path, err)\n\t\t\treturn err\n\t\t}\n","sourceCodeStart":1424,"sourceCodeEnd":1460,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/util/fsutil/fsutil.go#L1424-L1460","documentation":"ArchiveDir first os.Stat's the directory to archive; if the stat succeeds but the path is not a directory, it returns this sentinel error. It guards against archiving a regular file or symlink passed as the directory argument (a pre-existing os.Create(afname) would then clobber output).","triggerScenarios":"Calling fsutil.ArchiveDir (via archiveArtifacts) with a d2aname path that exists but is a regular file or symlink rather than a directory.","commonSituations":"Config pointing at an artifact file instead of the directory containing it, a directory replaced by a symlink after a deploy, or a path typo resolving to a file.","solutions":["Verify the path with os.Stat and info.IsDir() before calling ArchiveDir.","If you meant to archive a single file, use ArchiveFiles/Archive instead of ArchiveDir.","Fix the path configuration to point to the actual artifact directory."],"exampleFix":"// before\nfsutil.ArchiveDir(\"/out/artifacts.tar\", \"/cfg/artifacts.yaml\")\n// after\nif fi, err := os.Stat(\"/cfg/artifacts\"); err == nil && fi.IsDir() {\n    fsutil.ArchiveDir(\"/out/artifacts.tar\", \"/cfg/artifacts\")\n}","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(dirPath)\nif err != nil {\n    return fmt.Errorf(\"cannot access %s: %w\", dirPath, err)\n}\nif !fi.IsDir() {\n    return fmt.Errorf(\"%s is not a directory\", dirPath)\n}","typeGuard":null,"tryCatchPattern":"if err := fsutil.ArchiveDir(afname, dname); err != nil {\n    if err.Error() == \"not a directory\" {\n        return fmt.Errorf(\"configured artifact path %s is a file; fix config\", dname)\n    }\n    return err\n}","preventionTips":["Validate the directory path at config-load time, not at archive time.","Use explicit config keys distinguishing file vs directory artifact paths.","Check for symlinks that were turned into files by deployments."],"tags":["filesystem","archive","validation"],"backgroundTag":"not-a-directory","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}