vxcontrol/pentagi · error

failed to create temp directory

Error message

failed to create temp directory: %w

What it means

SaveToTemp creates the target directory with os.MkdirAll(dir, 0755) before writing; this error wraps whatever MkdirAll returned. It means the temp directory could not be created or verified, typically due to filesystem permissions or an invalid path.

Solutions

  1. Check permissions on dir and its parents (ls -ld) and chown/chmod so the service user can write
  2. Verify the configured directory path is correct and not accidentally pointing at a file
  3. Check disk space and mount status (df -h, mount) for read-only or full volumes
  4. Create the directory manually with correct ownership as a quick unblock, then fix provisioning

Example fix

// before
dir := "/var/lib/pentagi/resources" // root-owned
path, _, _, err := resources.SaveToTemp(r, dir)
// after
if err := os.MkdirAll(dir, 0755); err != nil {
    log.Fatalf("cannot use resources dir %s: %v", dir, err)
}
path, _, _, err := resources.SaveToTemp(r, dir)
Defensive patterns

Strategy: try-catch

Validate before calling

func canWriteDir(dir string) error {
	info, err := os.Stat(dir)
	if err == nil && !info.IsDir() {
		return fmt.Errorf("%s is a file, not a directory", dir)
	}
	if err := os.MkdirAll(dir, 0755); err != nil {
		return err
	}
	probe := filepath.Join(dir, ".write-probe")
	if err := os.WriteFile(probe, nil, 0644); err != nil {
		return err
	}
	return os.Remove(probe)
}

Try / catch

tmpPath, hash, size, err := resources.SaveToTemp(r, dir)
if err != nil {
	var perr *fs.PathError
	if errors.As(err, &perr) && errors.Is(perr.Err, syscall.EACCES) {
		return fmt.Errorf("resources dir %s not writable: %w", dir, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling SaveToTemp with a dir whose parent is read-only, which is a file rather than a directory, sits on a full/read-only volume, or uses characters invalid for the filesystem. Raised via UploadResources or direct calls.

Common situations: Container running as non-root writing to a root-owned path; Docker volume mounted read-only; NFS/permission issues after deployment; a configured resources directory pointing at a file after a bad env var edit.

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 vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/1d9dfc2ef2864638. Report an issue: GitHub.

Appendix: source

Thrown at backend/pkg/resources/resources.go:275

		return rest
	}
	return newPrefix + "/" + rest
}

// EscapeLike escapes special LIKE pattern characters (%, _) in s so the string
// can be safely embedded in a SQL LIKE clause.
func EscapeLike(s string) string {
	s = strings.ReplaceAll(s, `\`, `\\`)
	s = strings.ReplaceAll(s, `%`, `\%`)
	s = strings.ReplaceAll(s, `_`, `\_`)
	return s
}

// SaveToTemp writes r into a new temporary file in dir and returns the path to
// the temp file. The caller is responsible for removing the temp file on error.
func SaveToTemp(r io.Reader, dir string) (tmpPath string, hash string, size int64, err error) {
	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", "", 0, fmt.Errorf("failed to create temp directory: %w", err)
	}

	tmp, err := os.CreateTemp(dir, ".resource-upload-*")
	if err != nil {
		return "", "", 0, fmt.Errorf("failed to create temp file: %w", err)
	}
	tmpPath = tmp.Name()
	defer tmp.Close()

	h := md5.New()
	mw := io.MultiWriter(tmp, h)
	written, copyErr := io.Copy(mw, r)
	if copyErr != nil {
		os.Remove(tmpPath)
		return "", "", 0, fmt.Errorf("failed to write temp file: %w", copyErr)
	}
	if err := tmp.Chmod(0644); err != nil {
		os.Remove(tmpPath)

View on GitHub (pinned to ea665308ba)