vxcontrol/pentagi · error

failed to create file '%s': %w

Error message

failed to create file '%s': %w

What it means

ExtractTar opens each regular-file entry with os.OpenFile(entryPath, O_CREATE|O_WRONLY|O_TRUNC, 0644) after its parent directory exists; failure here aborts with this error. Because the path was already sanitized and parents created, causes are filesystem-level: permissions, read-only volume, name conflicts, or resource exhaustion (too many open files).

Source

Thrown at backend/pkg/flowfiles/files.go:420

			if hdr.Size < 0 {
				return fmt.Errorf("tar entry '%s' has invalid size %d", hdr.Name, hdr.Size)
			}
			filesCount++
			if filesCount > MaxPullFiles {
				return fmt.Errorf("tar archive exceeds maximum file count of %d", MaxPullFiles)
			}
			totalSize += hdr.Size
			if totalSize > MaxPullTotalSize {
				return fmt.Errorf("tar archive exceeds maximum total size of %d bytes", MaxPullTotalSize)
			}

			if err := os.MkdirAll(filepath.Dir(entryPath), 0755); err != nil {
				return fmt.Errorf("failed to create parent directory for '%s': %w", entryPath, err)
			}

			f, err := os.OpenFile(entryPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
			if err != nil {
				return fmt.Errorf("failed to create file '%s': %w", entryPath, err)
			}
			_, copyErr := io.CopyN(f, tr, hdr.Size)
			f.Close()
			if copyErr != nil {
				return fmt.Errorf("failed to write file '%s': %w", entryPath, copyErr)
			}
		}
	}

	return nil
}

func ZipDirectory(w io.Writer, dirPath string) (err error) {
	zw := zip.NewWriter(w)
	defer func() {
		if cerr := zw.Close(); err == nil {
			err = cerr
		}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Read the wrapped errno: EACCES/EROFS → fix volume permissions or mount rw; EISDIR → clear the conflicting directory from a prior extraction; EMFILE → raise ulimit -n or fix fd leaks.
  2. Sanitize/flatten entry names when producing the tar to avoid characters invalid on the target OS.
  3. Ensure the process user owns destDir (chown -R service:service destDir).
  4. Check disk space (ENOSPC) on the destination volume.

Example fix

// before
err := flowfiles.ExtractTar(rc, destDir)
// after
// run as the volume owner or pre-chown the dir:
// $ chown -R 10001:10001 /var/lib/pentagi/uploads
if err := os.MkdirAll(destDir, 0o755); err != nil { return err }
err := flowfiles.ExtractTar(rc, destDir)
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure destDir is writable and the process is under fd limits:
info, err := os.Stat(destDir)
if err != nil || !info.IsDir() {
    return fmt.Errorf("destDir missing or not a directory")
}
if err := unix.Access(destDir, unix.W_OK); err != nil {
    return fmt.Errorf("destDir not writable by current user: %w", err)
}

Try / catch

err := flowfiles.ExtractTar(rc, destDir)
if err != nil {
    var pe *fs.PathError
    if errors.As(err, &pe) {
        switch {
        case errors.Is(pe.Err, syscall.EACCES), errors.Is(pe.Err, syscall.EROFS):
            return fmt.Errorf("cannot write into %s (check ownership/mount): %w", destDir, err)
        case errors.Is(pe.Err, syscall.EMFILE), errors.Is(pe.Err, syscall.ENFILE):
            return fmt.Errorf("fd limit exhausted: %w", err)
        case errors.Is(pe.Err, syscall.EISDIR):
            return fmt.Errorf("stale directory blocks a file entry; clean destDir: %w", err)
        case errors.Is(pe.Err, syscall.ENOSPC):
            return fmt.Errorf("disk full: %w", err)
        }
    }
    return err
}

Prevention

When it happens

Trigger: os.OpenFile fails during PullFlowFiles extraction: destDir volume is read-only or lacks write permission, a directory already exists at entryPath (EISDIR), filename contains characters invalid for the host FS, EMFILE/ENFILE fd exhaustion, or disk full at open/truncate time.

Common situations: Archives built on case-sensitive/other-OS filesystems with characters like ':' or '\\' extracted onto stricter filesystems; service running as unprivileged UID against a root-owned volume; fd leaks elsewhere in the process hitting the ulimit.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/7d5ce4e077e3f8c3. Report an issue: GitHub.