{"record":{"id":"c1741bbc606fa900","repo":"vxcontrol/pentagi","slug":"s-is-not-a-regular-file","errorCode":null,"errorMessage":"'%s' is not a regular file","messagePattern":"'(.+?)' is not a regular file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":311,"sourceCode":"\nfunc LocalEntryExists(filePath string) (bool, error) {\n\tif _, err := os.Lstat(filePath); err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, err\n\t}\n\n\treturn true, nil\n}\n\nfunc RegularFileInfo(filePath string) (os.FileInfo, error) {\n\tinfo, err := os.Lstat(filePath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !info.Mode().IsRegular() {\n\t\treturn nil, fmt.Errorf(\"'%s' is not a regular file\", filePath)\n\t}\n\n\treturn info, nil\n}\n\nfunc SaveUploadedFileToTemp(fh *multipart.FileHeader, dir string) (string, error) {\n\tsrc, err := fh.Open()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to open uploaded file: %w\", err)\n\t}\n\tdefer src.Close()\n\n\tdst, err := os.CreateTemp(dir, \".upload-*\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create temporary upload file: %w\", err)\n\t}\n\ttmpPath := dst.Name()\n\tdefer dst.Close()","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L293-L329","documentation":"RegularFileInfo lstats the path and requires a regular file. If the Lstat succeeds but the entry is a directory, symlink, socket, FIFO, or device, it returns \"'<path>' is not a regular file\". UploadFlowFiles uses this to reject non-file uploads before streaming.","triggerScenarios":"Calling flowfiles.RegularFileInfo on a directory path, a symlink (Lstat does not follow links), or a special file (device/socket/FIFO) — e.g. when a user selects a folder for upload, or a path that turned out to be a symlink to a file.","commonSituations":"Uploading a directory instead of files from the UI/CLI; dragging a symlink into an upload form; referencing /dev/null or a Unix socket; a path that existed as a file but was replaced by a symlink between listing and upload (TOCTOU).","solutions":["Ensure the path refers to a regular file, not a directory or symlink, before calling.","If uploading a directory, enumerate its files and call the upload API per regular file.","Resolve symlinks first with filepath.EvalSymlinks or os.Stat if following links is intended, then check Mode().IsRegular() yourself."],"exampleFix":"// before\ninfo, err := flowfiles.RegularFileInfo(\"/data/mydir\")\n// after\nentries, _ := os.ReadDir(\"/data/mydir\")\nfor _, e := range entries {\n    if e.Type().IsRegular() {\n        info, err := flowfiles.RegularFileInfo(filepath.Join(\"/data/mydir\", e.Name()))\n        // handle info/err\n    }\n}","handlingStrategy":"validation","validationCode":"func ensureRegularFile(p string) error {\n    info, err := os.Stat(p) // Stat follows symlinks\n    if err != nil {\n        return err\n    }\n    if !info.Mode().IsRegular() {\n        return fmt.Errorf(\"%s is not a regular file\", p)\n    }\n    return nil\n}","typeGuard":"func isRegularFile(p string) bool {\n    info, err := os.Stat(p)\n    return err == nil && info.Mode().IsRegular()\n}","tryCatchPattern":"if err != nil {\n    if strings.HasSuffix(err.Error(), \"is not a regular file\") {\n        return fmt.Errorf(\"skip or expand directories/symlinks before upload: %w\", err)\n    }\n    return err\n}","preventionTips":["Reject directory picks in the upload UI before submitting.","Resolve or reject symlinks per your policy before upload.","Re-check the path right before upload to avoid TOCTOU swaps."],"tags":["go","filesystem","file-upload"],"backgroundTag":"not-a-regular-file","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}