OpenNHP/opennhp · error
error reading file
Error message
error reading file: %v
What it means
After successfully opening the data private key file in NewDataPrivateKeyStoreWith, io.ReadAll streams its content into memory. If the read fails mid-stream - typically I/O errors on the underlying descriptor - the function aborts with this wrapped error instead of returning a partially initialized store.
Solutions
- Inspect the wrapped os error and check disk/storage health of the volume containing etc/ztdo (dmesg, smartctl, mount status).
- Retry the load; transient I/O errors often clear after storage recovers.
- If the file is corrupt/unreadable, delete it, regenerate the key (Generate + Save) and re-register the ZTDO key with the provider.
- Ensure the process has adequate file descriptors (ulimit -n) if many files are open concurrently.
Example fix
// before: hard failure with no recovery
store, err := db.NewDataPrivateKeyStoreWith(doId)
if err != nil { log.Fatalf("%v", err) }
// after: bounded retry on transient I/O errors
var store *db.DataPrivateKeyStore
for i := 0; i < 3; i++ {
store, err = db.NewDataPrivateKeyStoreWith(doId)
if err == nil { break }
time.Sleep(time.Second)
} Defensive patterns
Strategy: retry
Validate before calling
f, err := os.Open(path)
if err != nil { return err }
info, err := f.Stat()
if err == nil && !info.Mode().IsRegular() { err = errors.New("not a regular file") }
f.Close() Type guard
func isTransientIO(err error) bool {
return errors.Is(err, syscall.EIO) || errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EINTR)
} Try / catch
var store *db.DataPrivateKeyStore
var err error
for attempt := 0; attempt < 3; attempt++ {
store, err = db.NewDataPrivateKeyStoreWith(doId)
if err == nil || !isTransientIO(errors.Unwrap(err)) { break }
time.Sleep(500 * time.Millisecond << attempt)
} Prevention
- Monitor disk health of the volume hosting etc/ztdo (SMART, dmesg alerts).
- Avoid network filesystems for key storage when possible; prefer local persistent volumes.
- Raise RLIMIT_NOFILE if the daemon opens many files concurrently.
- Keep key files tiny and replace them atomically to avoid partially visible writes.
When it happens
Trigger: Calling NewDataPrivateKeyStoreWith(doId) when the data-key-<doId>.json file becomes unreadable after opening: disk I/O error, file removed while reading on some systems, descriptor exhaustion, or hardware/NFS failure during read.
Common situations: Failing disk or full/under-provisioned network volume hosting etc/ztdo; NFS/ESXi stale handle after the storage backend re-mounted; running in a container whose writable layer hit an I/O error.
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
- fail to read resource
- error reading file
- failed to read file content
- failed to write JSON to file
- failed to read file
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/03325a04ba911cab.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/db/utils.go:47
}
}
// NewDataPrivateKeyStoreWith create a new DataPrivateKeyStore with doId
func NewDataPrivateKeyStoreWith(doId string) (d *DataPrivateKeyStore, err error) {
etcDir := "etc/ztdo"
fileName := "data-key-" + doId + ".json"
fullPath := filepath.Join(common.ExeDirPath, etcDir, fileName)
// open and read all the content in file
file, err := os.Open(fullPath)
if err != nil {
return nil, fmt.Errorf("failed to open file: %v", err)
}
fileContentByte, err := io.ReadAll(file)
if err != nil {
return nil, fmt.Errorf("error reading file: %v", err)
}
d = &DataPrivateKeyStore{}
_ = d.fromJson(fileContentByte)
return
}
func (d *DataPrivateKeyStore) Generate(mode ztdolib.DataKeyPairECCMode) (privateKey []byte) {
ecdh := core.NewECDH(mode.ToEccType())
d.DataPrivateKeyBase64 = ecdh.PrivateKeyBase64()
return ecdh.PrivateKey()
}
// Save saves the dataPrivateKeyBase64 to a file, the format of file name is data-<doId>.json
// Notes: this default way to store data private key is not safe. In the wild environment, need to use a secure way to store data private key.
func (d *DataPrivateKeyStore) Save(doId string) error {
// Make sure the etc directory existsView on GitHub (pinned to 6e04ca5ff0)