projectdiscovery/nuclei · error

failed to create file: %w

Error message

failed to create file: %w

What it means

After downloading and rewriting an OpenAPI spec, the downloader writes it to <TempDir>/openapi/openapi-spec-<unixtime>.json; os.Create on that path failed and the underlying filesystem error (permission denied, no such file or directory, read-only file system, disk full) is wrapped with %w. TempDir comes from the InputOptions.TempDir the caller (input provider) supplied.

Source

Thrown at pkg/input/formats/openapi/downloader.go:118

	modifiedJSON, err := json.Marshal(spec)
	if err != nil {
		return "", errors.Wrap(err, "failed to marshal modified spec")
	}

	// Create output directory
	openapiDir := filepath.Join(tmpDir, "openapi")
	if err := os.MkdirAll(openapiDir, 0755); err != nil {
		return "", errors.Wrap(err, "failed to create openapi directory")
	}

	// Generate filename
	filename := fmt.Sprintf("openapi-spec-%d.json", time.Now().Unix())
	filePath := filepath.Join(openapiDir, filename)

	// Write file
	file, err := os.Create(filePath)
	if err != nil {
		return "", fmt.Errorf("failed to create file: %w", err)
	}

	defer func() {
		_ = file.Close()
	}()

	if _, writeErr := file.Write(modifiedJSON); writeErr != nil {
		_ = os.Remove(filePath)
		return "", errors.Wrap(writeErr, "failed to write OpenAPI spec to file")
	}

	return filePath, nil
}

// SupportedExtensions returns the list of supported file extensions for OpenAPI
func (d *OpenAPIDownloader) SupportedExtensions() []string {
	return []string{".json"}
}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Set a writable TempDir (InputOptions.TempDir) or ensure $TMPDIR points at a writable directory
  2. Verify with `touch <tmpdir>/openapi/test` that the effective user can create files there
  3. In containers, mount an emptyDir/tmpfs at /tmp or set TMPDIR to a writable volume
  4. Free disk space or raise the tmpfs size limit if the volume is full

Example fix

// SDK usage: pass a writable temp dir
// before
opts := provider.InputOptions{Options: options}
// after
opts := provider.InputOptions{
    Options: options,
    TempDir: os.TempDir(), // or a known-writable dir like "/var/tmp/nuclei"
}
Defensive patterns

Strategy: validation

Validate before calling

dir := filepath.Join(tempDir, "openapi")
if err := os.MkdirAll(dir, 0o755); err != nil {
    return fmt.Errorf("temp dir not writable: %w", err)
}
probe, err := os.Create(filepath.Join(dir, ".writecheck"))
if err != nil {
    return fmt.Errorf("cannot create files in %s: %w", dir, err)
}
probe.Close()
os.Remove(probe.Name())

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to create file") {
    // point TempDir at a writable volume and retry once; otherwise fail with the FS error
}

Prevention

When it happens

Trigger: TempDir unset or pointing at a non-existent/read-only location; containers with a read-only rootfs and no writable /tmp; SELinux/AppArmor denying writes; disk exhausted; a file already existing where the openapi directory should be created; path too long.

Common situations: Running nuclei in hardened Docker/Kubernetes pods with read-only filesystems; minimal images lacking /tmp; CI runners with tiny tmpfs quotas; SDK callers passing an empty or relative TempDir.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/b201c09250bffbe2. Report an issue: GitHub.