{"record":{"id":"03325a04ba911cab","repo":"OpenNHP/opennhp","slug":"error-reading-file-v","errorCode":null,"errorMessage":"error reading file: %v","messagePattern":"error reading file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/db/utils.go","lineNumber":47,"sourceCode":"\t}\n}\n\n// NewDataPrivateKeyStoreWith create a new DataPrivateKeyStore with doId\nfunc NewDataPrivateKeyStoreWith(doId string) (d *DataPrivateKeyStore, err error) {\n\tetcDir := \"etc/ztdo\"\n\tfileName := \"data-key-\" + doId + \".json\"\n\n\tfullPath := filepath.Join(common.ExeDirPath, etcDir, fileName)\n\n\t// open and read all the content in file\n\tfile, err := os.Open(fullPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open file: %v\", err)\n\t}\n\n\tfileContentByte, err := io.ReadAll(file)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading file: %v\", err)\n\t}\n\n\td = &DataPrivateKeyStore{}\n\t_ = d.fromJson(fileContentByte)\n\n\treturn\n}\n\nfunc (d *DataPrivateKeyStore) Generate(mode ztdolib.DataKeyPairECCMode) (privateKey []byte) {\n\tecdh := core.NewECDH(mode.ToEccType())\n\td.DataPrivateKeyBase64 = ecdh.PrivateKeyBase64()\n\treturn ecdh.PrivateKey()\n}\n\n// Save saves the dataPrivateKeyBase64 to a file, the format of file name is data-<doId>.json\n// 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.\nfunc (d *DataPrivateKeyStore) Save(doId string) error {\n\t// Make sure the etc directory exists","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/db/utils.go#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: hard failure with no recovery\nstore, err := db.NewDataPrivateKeyStoreWith(doId)\nif err != nil { log.Fatalf(\"%v\", err) }\n// after: bounded retry on transient I/O errors\nvar store *db.DataPrivateKeyStore\nfor i := 0; i < 3; i++ {\n\tstore, err = db.NewDataPrivateKeyStoreWith(doId)\n\tif err == nil { break }\n\ttime.Sleep(time.Second)\n}","handlingStrategy":"retry","validationCode":"f, err := os.Open(path)\nif err != nil { return err }\ninfo, err := f.Stat()\nif err == nil && !info.Mode().IsRegular() { err = errors.New(\"not a regular file\") }\nf.Close()","typeGuard":"func isTransientIO(err error) bool {\n\treturn errors.Is(err, syscall.EIO) || errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EINTR)\n}","tryCatchPattern":"var store *db.DataPrivateKeyStore\nvar err error\nfor attempt := 0; attempt < 3; attempt++ {\n\tstore, err = db.NewDataPrivateKeyStoreWith(doId)\n\tif err == nil || !isTransientIO(errors.Unwrap(err)) { break }\n\ttime.Sleep(500 * time.Millisecond << attempt)\n}","preventionTips":["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."],"tags":["filesystem","io","read-error"],"backgroundTag":"file-read-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}