crowdsecurity/crowdsec · error
while reading symlink: %w
Error message
while reading symlink: %w
What it means
After confirming the local path is a symlink, RemoveInstallLink reads the link target. If os.Readlink fails, the error is wrapped as 'while reading symlink: %w'. This is rare: it means the symlink disappeared between the stat and readlink, or the OS rejected the call.
Source
Thrown at pkg/hubops/disable.go:27
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
)
// RemoveInstallLink removes the item's symlink between the installation directory and the local hub.
func RemoveInstallLink(i *cwhub.Item) error {
stat, err := os.Lstat(i.State.LocalPath)
if err != nil {
return err
}
// if it's managed by hub, it's a symlink to csconfig.GConfig.hub.HubDir / ...
if stat.Mode()&os.ModeSymlink == 0 {
return fmt.Errorf("%s isn't managed by hub", i.Name)
}
target, err := os.Readlink(i.State.LocalPath)
if err != nil {
return fmt.Errorf("while reading symlink: %w", err)
}
if target != i.State.DownloadPath {
return fmt.Errorf("%s isn't managed by hub", i.Name)
}
if err := os.Remove(i.State.LocalPath); err != nil {
return fmt.Errorf("while removing symlink: %w", err)
}
i.State.LocalPath = ""
return nil
}
// DisableCommand uninstalls an item and its dependencies, ensuring that no
// sub-item is left in an inconsistent state.
type DisableCommand struct {View on GitHub (pinned to 909b515798)
Solutions
- Ensure only one cscli process modifies the config directory at a time
- Re-list items ('cscli hub list') to refresh state, then retry
- Reinstall the item if the state is inconsistent
Example fix
// before
if err := RemoveInstallLink(item); err != nil { ... }
// after
if err := acquireConfigLock(); err != nil { return err }
defer releaseConfigLock()
if err := RemoveInstallLink(item); err != nil { ... } Defensive patterns
Strategy: validation
Validate before calling
target, err := os.Readlink(item.State.LocalPath)
if err != nil { return fmt.Errorf("symlink vanished: %w", err) } Try / catch
if err := hubops.RemoveInstallLink(item); err != nil {
if errors.Is(err, fs.ErrNotExist) { /* refresh state and retry once */ }
return err
} Prevention
- Serialize cscli operations with a lock
- Re-list hub state before mutating operations
- Retry once on ErrNotExist after refreshing state
When it happens
Trigger: Calling RemoveInstallLink when the symlink is concurrently removed/modified, or on a filesystem that does not support readlink on that path.
Common situations: Concurrent cscli runs racing on the same config directory; broken filesystem state; the item file was deleted by another process between checks.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- too many levels of symbolic links
- %s is already installed at %s
- file '%s' is not from hub '%s' nor from the configuration di
- %s isn't managed by hub
- while removing symlink: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/92e69f8acf72dbae.
Report an issue: GitHub.