crowdsecurity/crowdsec · error

unable to copy '%s' to '%s': %w

Error message

unable to copy '%s' to '%s': %w

What it means

After computing the destination inside the runtime hub, installPostoverflowItem copies the item file with Copy(). If the copy fails (source unreadable, destination not writable, missing directories), the error is wrapped naming both source and destination paths. This blocks the postoverflow from being installed for the hub test.

Source

Thrown at pkg/hubtest/postoverflow.go:33

		return fmt.Errorf("can't get absolute path of '%s': %w", sourcePath, err)
	}

	sourceFilename := filepath.Base(sourcePath)

	// runtime/hub/postoverflows/s00-enrich/crowdsecurity/
	hubDirPostoverflowDest := filepath.Join(t.RuntimeHubPath, filepath.Dir(item.RemotePath))

	// runtime/postoverflows/s00-enrich
	itemTypeDirDest := fmt.Sprintf("%s/postoverflows/%s/", t.RuntimePath, item.Stage)

	if err := createDirs([]string{hubDirPostoverflowDest, itemTypeDirDest}); err != nil {
		return err
	}

	// runtime/hub/postoverflows/s00-enrich/crowdsecurity/rdns.yaml
	hubDirPostoverflowPath := filepath.Join(hubDirPostoverflowDest, sourceFilename)
	if err := Copy(sourcePath, hubDirPostoverflowPath); err != nil {
		return fmt.Errorf("unable to copy '%s' to '%s': %w", sourcePath, hubDirPostoverflowPath, err)
	}

	// runtime/postoverflows/s00-enrich/rdns.yaml
	postoverflowDirParserPath := filepath.Join(itemTypeDirDest, sourceFilename)
	if err := os.Symlink(hubDirPostoverflowPath, postoverflowDirParserPath); err != nil {
		if !os.IsExist(err) {
			return fmt.Errorf("unable to symlink postoverflow '%s' to '%s': %w", hubDirPostoverflowPath, postoverflowDirParserPath, err)
		}
	}

	return nil
}

func (t *HubTestItem) installPostoverflowCustomFrom(postoverflow string, customPath string) (bool, error) {
	// we check if its a custom postoverflow
	customPostOverflowPath := filepath.Join(customPath, postoverflow)
	if _, err := os.Stat(customPostOverflowPath); os.IsNotExist(err) {
		return false, nil

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the wrapped Copy error for the exact OS-level cause (ENOENT/EACCES)
  2. Ensure the runtime hub postoverflow directory exists and is writable
  3. Verify the source item file exists at t.HubPath/<RemotePath>
  4. Re-run `cscli hub update` if hub files are missing/corrupt
Defensive patterns

Strategy: try-catch

Validate before calling

src := filepath.Join(t.HubPath, item.RemotePath)
if _, err := os.Stat(src); err != nil {
    return fmt.Errorf("source missing: %w", err)
}
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
    return fmt.Errorf("dest dir: %w", err)
}

Try / catch

if err := t.installPostoverflow(item); err != nil {
    var perr *os.PathError
    if errors.As(errors.Unwrap(err), &perr) {
        log.Errorf("fs failure on %s: %v", perr.Path, perr.Err)
    }
    return err
}

Prevention

When it happens

Trigger: Copy(sourcePath, hubDirPostoverflowPath) fails: source file missing, target directory absent (hub dir creation failed earlier), or permission issues.

Common situations: Runtime hub directory not created due to earlier mkdir failure; read-only test runtime tree; hub item deleted between enumeration and install; disk full.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/502e8dad19e59ac7. Report an issue: GitHub.