OpenNHP/opennhp · error

could not get file info

Error message

could not get file info: %v

What it means

After opening the file, UploadFileToNHPServer calls file.Stat() to learn the total size for upload progress tracking. The error 'could not get file info: %v' wraps a Stat failure on an already-open file descriptor. On Linux this usually fails because the file was truncated/removed mid-flight, or on exotic filesystems where fstat is unsupported.

Solutions

  1. Ensure no external process deletes or truncates the file during upload
  2. Point the upload at a regular file on a local filesystem instead of a pipe/device
  3. Re-run the upload; transient FUSE/NFS stat errors are usually momentary
  4. Check filesystem health (dmesg for I/O errors) if persistent

Example fix

// before
_, err = udpDevice.UploadFileToNHPServer(ztdoPath)
// after
info, err := os.Stat(ztdoPath)
if err != nil || !info.Mode().IsRegular() {
    return fmt.Errorf("%s is not a readable regular file", ztdoPath)
}
_, err = udpDevice.UploadFileToNHPServer(ztdoPath)
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(path)
if err != nil {
    return fmt.Errorf("cannot stat %s: %w", path, err)
}
if !info.Mode().IsRegular() {
    return fmt.Errorf("%s is not a regular file; fstat size may be unavailable", path)
}

Type guard

func isStattable(path string) bool {
    _, err := os.Stat(path)
    return err == nil
}

Try / catch

url, err := dev.UploadFileToNHPServer(filePath)
if err != nil {
    if strings.Contains(err.Error(), "could not get file info") {
        return fmt.Errorf("file changed or filesystem rejected stat on %s: %w", filePath, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling UploadFileToNHPServer on a file that is deleted or truncated between os.Open and file.Stat(); or Stat failing on special/character devices or FUSE mounts that reject fstat.

Common situations: A cleanup job or another process removes the file during upload startup; the path points at /dev/stdin or a pipe where size is undefined; a network filesystem that errors on fstat.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/c670f629636b7e59. Report an issue: GitHub.

Appendix: source

Thrown at endpoints/db/utils.go:212

	httpHost := fmt.Sprintf("http://%s/", a.GetServerPeer().Host())
	testReq, err := http.Get(httpHost) //nolint:gosec // G107: URL constructed from configured server peer
	if err != nil {
		return "", err
	}

	if testReq.StatusCode == http.StatusBadRequest {
		httpHost = fmt.Sprintf("https://%s/", a.GetServerPeer().Host())
	}

	file, err := os.Open(filePath)
	if err != nil {
		return "", fmt.Errorf("could not open file: %v", err)
	}
	defer file.Close()

	fileInfo, err := file.Stat()
	if err != nil {
		return "", fmt.Errorf("could not get file info: %v", err)
	}

	// create upload progress
	progress := &UploadProgress{
		TotalSize: fileInfo.Size(),
	}

	startTime := time.Now()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile("file", filepath.Base(filePath))
	if err != nil {
		return "", fmt.Errorf("could not create form file: %v", err)
	}

	progressReader := &ProgressReader{

View on GitHub (pinned to 6e04ca5ff0)