crowdsecurity/crowdsec · error
%s is already downloaded at %s
Error message
%s is already downloaded at %s
What it means
Item.PathForDownload computes where an item should be downloaded. If the item is already downloaded but the newly computed path differs from the recorded State.DownloadPath, the same-named item lives in two locations — an inconsistent state the library refuses to guess about, returning an error.
Source
Thrown at pkg/cwhub/item.go:145
if i.Stage != "" {
p = filepath.Join(p, i.Stage)
}
return SafePath(i.hub.local.InstallDir, filepath.Join(p, i.FileName))
}
// PathForDownload returns the path to use to store the item's file from the hub
// (eg. /etc/crowdsec/hub/collections/author/xyz.yaml).
// Raises an error if the path goes outside of the hub dir.
func (i *Item) PathForDownload() (string, error) {
path, err := SafePath(i.hub.local.HubDir, i.RemotePath)
if i.State.IsDownloaded() && path != i.State.DownloadPath {
// A hub item with the same name is at a different location.
// This should not happen.
// user is downloading with --force so we are allowed to overwrite but
// should we remove the old location from here? Error, warning, more tests?
return "", fmt.Errorf("%s is already downloaded at %s", i.FQName(), i.State.DownloadPath)
}
return path, err
}
// HasSubItems returns true if items of this type can have sub-items. Currently only collections.
func (i *Item) HasSubItems() bool {
return i.Type == COLLECTIONS
}
// MarshalJSON is used to prepare the output for "cscli ... inspect -o json".
// It must not use a pointer receiver.
func (i Item) MarshalJSON() ([]byte, error) {
type Alias Item
return json.Marshal(&struct {
Alias
// we have to repeat the fields here, json will have inline support in v2View on GitHub (pinned to 909b515798)
Solutions
- Remove the stale file at i.State.DownloadPath (or `cscli hub remove` the item) and re-download
- Re-align config so install/hub dirs match where items were originally downloaded
- Reset hub state by re-running `cscli hub update` and reinstalling affected items
- If intentional, clear the item's State before calling PathForDownload
Example fix
// before path, err := item.PathForDownload(downloadDir) // errors: different location // after os.Remove(item.State.DownloadPath) // clean stale copy first path, err := item.PathForDownload(downloadDir)
Defensive patterns
Strategy: try-catch
Validate before calling
if item.State.IsDownloaded() {
expected, _ := item.PathForDownload(dir) // may error; compare first
_ = expected
} Try / catch
path, err := item.PathForDownload(dir)
if err != nil && strings.Contains(err.Error(), "already downloaded") {
os.Remove(item.State.DownloadPath)
path, err = item.PathForDownload(dir)
} Prevention
- Don't change hub/install directory config after items are installed
- Keep item type/stage metadata consistent with on-disk layout
- Reinstall items after moving crowdsec config directories
When it happens
Trigger: Downloading (even with --force) an item whose State.DownloadPath points somewhere else than the path derived from the current hub configuration — e.g. the install dir or item type mapping changed between runs.
Common situations: Moving or renaming the hub/install directories in config after items were downloaded; changing item type/stage so the computed path shifts; corrupted State from manual file moves.
Related errors
- while downloading data for %s: %w
- while getting data: %w
- %s: %w
- can't enable %s: not downloaded
- unable to download data for parser '%s': %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/f138febdc6591de7.
Report an issue: GitHub.