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
- Ensure no external process deletes or truncates the file during upload
- Point the upload at a regular file on a local filesystem instead of a pipe/device
- Re-run the upload; transient FUSE/NFS stat errors are usually momentary
- 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
- Freeze the file (no concurrent writers/deleters) during upload
- Prefer local filesystems over FUSE/network mounts for upload sources
- Check dmesg for I/O errors if stat failures recur
- Avoid uploading from /dev/stdin or pipes
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
- resource not found
- could not create form file
- could not copy file to server
- fail to create private key directory
- fail to create public key directory
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)