crowdsecurity/crowdsec · error

unable to create folder '%s': %w

Error message

unable to create folder '%s': %w

What it means

This error is returned by HubTestItem.Run when os.MkdirAll fails to create the appsec-configs directory under the test runtime path. Note the message reports t.RuntimePath rather than the exact subdirectory being created; the wrapped error is the OS-level mkdir failure (permission, existing non-directory file, etc.).

Source

Thrown at pkg/hubtest/hubtest_item.go:639

	// copy template profile file to runtime folder
	if err = Copy(t.TemplateProfilePath, t.RuntimeProfileFilePath); err != nil {
		return fmt.Errorf("unable to copy '%s' to '%s': %w", t.TemplateProfilePath, t.RuntimeProfileFilePath, err)
	}

	// copy template simulation file to runtime folder
	if err = Copy(t.TemplateSimulationPath, t.RuntimeSimulationFilePath); err != nil {
		return fmt.Errorf("unable to copy '%s' to '%s': %w", t.TemplateSimulationPath, t.RuntimeSimulationFilePath, err)
	}

	// copy template patterns folder to runtime folder
	if err = CopyDir(patternDir, t.RuntimePatternsPath); err != nil {
		return fmt.Errorf("unable to copy 'patterns' from '%s' to '%s': %w", patternDir, t.RuntimePatternsPath, err)
	}

	// create the appsec-configs dir
	if err = os.MkdirAll(filepath.Join(t.RuntimePath, "appsec-configs"), os.ModePerm); err != nil {
		return fmt.Errorf("unable to create folder '%s': %w", t.RuntimePath, err)
	}

	// if it's an appsec rule test, we need acquis and appsec profile
	if len(t.Config.AppsecRules) > 0 {
		// copy template acquis file to runtime folder
		log.Debugf("copying %s to %s", t.TemplateAcquisPath, t.RuntimeAcquisFilePath)

		if err = Copy(t.TemplateAcquisPath, t.RuntimeAcquisFilePath); err != nil {
			return fmt.Errorf("unable to copy '%s' to '%s': %w", t.TemplateAcquisPath, t.RuntimeAcquisFilePath, err)
		}

		log.Debugf("copying %s to %s", t.TemplateAppsecProfilePath, filepath.Join(t.RuntimePath, "appsec-configs", "config.yaml"))
		// copy template appsec-config file to runtime folder
		if err = Copy(t.TemplateAppsecProfilePath, filepath.Join(t.RuntimePath, "appsec-configs", "config.yaml")); err != nil {
			return fmt.Errorf("unable to copy '%s' to '%s': %w", t.TemplateAppsecProfilePath, filepath.Join(t.RuntimePath, "appsec-configs", "config.yaml"), err)
		}
	} else { // otherwise we drop a blank acquis file
		if err = os.WriteFile(t.RuntimeAcquisFilePath, []byte(""), os.ModePerm); err != nil {

View on GitHub (pinned to 909b515798)

Solutions

  1. Delete the stale runtime directory (t.RuntimePath) and re-run the test so directories are recreated cleanly.
  2. Check whether 'appsec-configs' exists as a plain file in the runtime path and remove it.
  3. Verify the current user has write permission on t.RuntimePath.
  4. Check disk space / read-only mount status.

Example fix

// before
item.Run(ctx, patternDir) // "unable to create folder ...: mkdir ...: file exists"
// after: clean runtime before running
os.RemoveAll(item.RuntimePath)
if err := item.Run(ctx, patternDir); err != nil { ... }
Defensive patterns

Strategy: validation

Validate before calling

p := filepath.Join(item.RuntimePath, "appsec-configs")
if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
    return fmt.Errorf("%s exists and is not a directory; remove it", p)
}
os.RemoveAll(item.RuntimePath) // or ensure clean state

Try / catch

if err := item.Run(ctx, patternDir); err != nil {
    if errors.Is(errors.Unwrap(err), syscall.EEXIST) || os.IsPermission(errors.Unwrap(err)) {
        os.RemoveAll(item.RuntimePath)
        return item.Run(ctx, patternDir) // one clean retry
    }
    return err
}

Prevention

When it happens

Trigger: HubTestItem.Run is called and a file named 'appsec-configs' already exists at filepath.Join(t.RuntimePath, "appsec-configs"), or the runtime directory is unwritable, or the filesystem is full/read-only.

Common situations: Leftover runtime folder where a previous run created appsec-configs as something other than a directory; running tests as a user without write access to the runtime path; read-only CI artifact mount or full disk.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


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