vxcontrol/pentagi · error

failed to create temp directory: %w

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.

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)

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.