{"record":{"id":"9726b15a1f4a5340","repo":"crowdsecurity/crowdsec","slug":"q-is-a-directory-not-a-file","errorCode":null,"errorMessage":"%q is a directory, not a file","messagePattern":"%q is a directory, not a file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/hubtest/hubtest.go","lineNumber":97,"sourceCode":"\t\tresolved = absPath\n\tdefault:\n\t\tp, err := exec.LookPath(binary)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tresolved = p\n\t}\n\n\tf, err := os.Stat(resolved)\n\tswitch {\n\tcase errors.Is(err, fs.ErrNotExist):\n\t\treturn \"\", err\n\tcase err != nil:\n\t\treturn \"\", err\n\t}\n\n\tif f.IsDir() {\n\t\treturn \"\", fmt.Errorf(\"%q is a directory, not a file\", resolved)\n\t}\n\n\treturn resolved, nil\n}\n\nfunc NewHubTest(hubPath string, crowdsecPath string, cscliPath string, isAppsecTest bool) (HubTest, error) {\n\thubPath, err := filepath.Abs(hubPath)\n\tif err != nil {\n\t\treturn HubTest{}, fmt.Errorf(\"can't get absolute path of hub: %w\", err)\n\t}\n\n\tsharedDataDir := filepath.Join(hubPath, \".cache\", \"data\")\n\tif err = os.MkdirAll(sharedDataDir, 0o700); err != nil {\n\t\treturn HubTest{}, fmt.Errorf(\"while creating data dir: %w\", err)\n\t}\n\n\t// we can't use hubtest without the hub\n\tif _, err = os.Stat(hubPath); os.IsNotExist(err) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/hubtest/hubtest.go#L79-L115","documentation":"resolveBinaryPath stats a candidate binary path and refuses to return a directory: if the resolved path IsDir, it errors with '%q is a directory, not a file'. This prevents hubtest from trying to execute a directory as the crowdsec/cscli binary.","triggerScenarios":"Calling NewHubTest with crowdsecPath or cscliPath pointing at a directory (e.g. a directory literally named 'crowdsec', or a bin dir passed instead of the binary inside it).","commonSituations":"Passing '/usr/local/bin' instead of '/usr/local/bin/crowdsec'; a build step leaving a directory where the binary should be; 'make build' output path misconfigured in scripts.","solutions":["Point crowdsecPath/cscliPath at the binary file itself, not its containing directory","Run 'make build' so the binaries exist at the expected path, then pass e.g. ./crowdsec/crowdsec","Check with ls -la that the path is a regular executable file"],"exampleFix":"// before\nNewHubTest(hubPath, \"/path/to/crowdsec/\", cscliPath, false)  // directory\n// after\nNewHubTest(hubPath, \"/path/to/crowdsec/crowdsec\", cscliPath, false)","handlingStrategy":"validation","validationCode":"info, err := os.Stat(binPath)\nif err != nil { return err }\nif info.IsDir() { return fmt.Errorf(\"%s is a directory; pass the binary file\", binPath) }\nif info.Mode()&0o111 == 0 { return fmt.Errorf(\"%s is not executable\", binPath) }","typeGuard":null,"tryCatchPattern":"ht, err := hubtest.NewHubTest(hubPath, crowdsecPath, cscliPath, false)\nif err != nil {\n    if strings.Contains(err.Error(), \"is a directory\") { /* point at the binary file and retry */ }\n}","preventionTips":["Pass the full path to the binary file, not its directory","Run make build before hubtest so binaries exist","ls -la the path when configuring test scripts"],"tags":["binary","filesystem","hubtest","cli"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}