{"record":{"id":"4d2a57a4563c9ee5","repo":"crowdsecurity/crowdsec","slug":"while-creating-symlink-from-s-to-s-w","errorCode":null,"errorMessage":"while creating symlink from %s to %s: %w","messagePattern":"while creating symlink from (.+?) to (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/hubops/enable.go","lineNumber":72,"sourceCode":"\t\treturn err\n\t}\n\n\tdestDir := filepath.Dir(dest)\n\tif err = os.MkdirAll(destDir, os.ModePerm); err != nil {\n\t\treturn fmt.Errorf(\"while creating %s: %w\", destDir, err)\n\t}\n\n\tif _, err = os.Lstat(dest); err == nil {\n\t\t// already exists\n\t\treturn nil\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to stat %s: %w\", dest, err)\n\t}\n\n\tsrc := i.State.DownloadPath\n\n\tif err = os.Symlink(src, dest); err != nil {\n\t\treturn fmt.Errorf(\"while creating symlink from %s to %s: %w\", src, dest, err)\n\t}\n\n\ti.State.LocalPath = dest\n\n\treturn nil\n}\n\nfunc (c *EnableCommand) Run(_ context.Context, plan *ActionPlan) error {\n\ti := c.Item\n\n\tfmt.Fprintln(os.Stdout, \"enabling \" + colorizeItemName(i.FQName()))\n\n\tif !i.State.IsDownloaded() {\n\t\t// XXX: this a warning?\n\t\treturn fmt.Errorf(\"can't enable %s: not downloaded\", i.FQName())\n\t}\n\n\tif err := CreateInstallLink(i); err != nil {","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/hubops/enable.go#L54-L90","documentation":"os.Symlink(src, dest) failed while linking the item's downloaded file (i.State.DownloadPath) into the install directory. The error names both ends of the link (src → dest) so the user can diagnose either side.","triggerScenarios":"During CreateInstallLink when creating the symlink fails: dest already exists (raced with Lstat check), src (DownloadPath) doesn't exist or is on a different filesystem/snapshot, or the user lacks write permission on destDir.","commonSituations":"Hub data dir and /etc/crowdsec on different mounts with hardlink-only tooling assumptions; the downloaded item was cleaned up between download and enable; container volume setups with restricted symlink permissions; two cscli processes racing on the same item.","solutions":["Verify src exists: `ls -l <src>`; re-run `cscli hub update && cscli <type> install <item>` if it's missing.","Remove any existing file/symlink at dest, then retry the enable command.","Ensure both paths are on the same accessible filesystem and the crowdsec user can write destDir.","Avoid running concurrent cscli hub operations; retry the command once the race is resolved."],"exampleFix":"// before: dest exists from a previous partial enable\nsudo rm -f /etc/crowdsec/parsers/sudo\nsudo cscli parsers enable sudo","handlingStrategy":"try-catch","validationCode":"if _, err := os.Lstat(dest); err == nil {\n    return fmt.Errorf(\"destination %s already exists\", dest)\n}\nif _, err := os.Stat(src); err != nil {\n    return fmt.Errorf(\"download path %s missing\", src)\n}","typeGuard":null,"tryCatchPattern":"if err := os.Symlink(src, dest); err != nil {\n    if errors.Is(err, os.ErrExist) {\n        os.Remove(dest)\n        return os.Symlink(src, dest)\n    }\n    return err\n}","preventionTips":["Don't run concurrent cscli hub operations on the same host.","Keep the hub data dir and the install dir on accessible filesystems.","Re-download the item if its DownloadPath file disappeared before enabling.","Confirm container volume mounts allow symlink creation in /etc/crowdsec."],"tags":["filesystem","symlink","permissions","hub"],"backgroundTag":"file-write-failed","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"}