{"record":{"id":"c8f07c336f6591e3","repo":"OpenNHP/opennhp","slug":"failed-to-create-config-json-v","errorCode":null,"errorMessage":"failed to create config.json: %v","messagePattern":"failed to create config\\.json: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/server/msghandler.go","lineNumber":740,"sourceCode":"\t\tif drgMsg.AccessUrl == \"\" { // provider update access url\n\t\t\tdrgMsg.AccessUrl = existingDrgMsg.AccessUrl\n\t\t}\n\n\t\tos.Remove(configPath)\n\t}\n\n\t// Make sure the etc directory exists\n\tif err := os.MkdirAll(etcDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create etc directory: %v\", err)\n\t}\n\n\tif _, err := os.Stat(configPath); err == nil {\n\t\treturn fmt.Errorf(\"%v already exists, please delete it first\", configFileName)\n\t}\n\n\tfile, err := os.Create(configPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create config.json: %v\", err)\n\t}\n\tdefer file.Close()\n\n\tencoder := json.NewEncoder(file)\n\tencoder.SetIndent(\"\", \"  \")\n\treturn encoder.Encode(drgMsg)\n}\n\n// read data-<doId>.json to DRGMsg Object\nfunc ReadZdtoConfig(doId string) (common.DRGMsg, error) {\n\tetcDir := filepath.Join(ExeDirPath, \"etc\", \"ztdo\")\n\tconfigFilePath := filepath.Join(etcDir, \"data-\"+doId+\".json\")\n\tfile, err := os.Open(configFilePath)\n\tif err != nil {\n\t\treturn common.DRGMsg{}, fmt.Errorf(\"could not open file: %v\", err)\n\t}\n\tdefer file.Close()\n","sourceCodeStart":722,"sourceCodeEnd":758,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/server/msghandler.go#L722-L758","documentation":"SaveZdtoConfig could not create (or truncate) the file `etc/ztdo/data-<doId>.json`. os.Create returned an error — the message text says \"failed to create config.json\" but it wraps the OS error from creating the ztdo data config. The DRG update is aborted.","triggerScenarios":"HandleDHPDRGMessage → SaveZdtoConfig calls os.Create on a path in an unwritable directory, the disk is full, the path exceeds filesystem name limits (very long doId), or the name is invalid for the filesystem.","commonSituations":"Disk-full on the server volume hosting etc/ztdo; read-only mount after the earlier MkdirAll check raced with a remount; a doId containing characters illegal on the target filesystem.","solutions":["Inspect the wrapped %v OS error and fix the cause (disk full: free space; permission: chown/chmod etc/ztdo).","Confirm the filesystem containing ExeDirPath is writable at write time (mount options, rw remount).","Validate the doId — reject/control excessively long or filesystem-illegal characters before persisting configs.","Retry the DHP DRG operation once storage is healthy."],"exampleFix":"// before: no guard on doId characters\nconfigFileName := \"data-\" + objectId + \".json\"\n// after: sanitize before building the path\nsafeId := strings.Map(func(r rune) rune { if r=='/'||r=='\\\\'||r==0 {return -1}; return r }, objectId)\nconfigFileName := \"data-\" + safeId + \".json\"","handlingStrategy":"try-catch","validationCode":"dir := filepath.Join(exeDir, \"etc\", \"ztdo\")\nos.MkdirAll(dir, 0o755)\nif err := syscall.Access(dir, syscall.O_RDWR); err != nil {\n    return fmt.Errorf(\"ztdo dir not writable: %v\", err)\n}","typeGuard":"func canCreateIn(dir string) bool {\n    p := filepath.Join(dir, \".probe\")\n    f, err := os.Create(p)\n    if err != nil { return false }\n    f.Close(); os.Remove(p)\n    return true\n}","tryCatchPattern":"if err := SaveZdtoConfig(drg); err != nil && strings.Contains(err.Error(), \"failed to create config.json\") {\n    log.Error(\"ztdo write failed: %v — check disk space and permissions\", err)\n    freeDiskOrRemount(); err = SaveZdtoConfig(drg)\n}","preventionTips":["Monitor disk space on the volume hosting etc/ztdo.","Keep doIds short and filesystem-safe; sanitize path characters.","Alert on read-only remounts of the state volume."],"tags":["filesystem","disk","config"],"backgroundTag":"file-write-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"}