{"record":{"id":"292b77d6f6914f96","repo":"AdguardTeam/AdGuardHome","slug":"writing-new-config-w","errorCode":null,"errorMessage":"writing new config: %w","messagePattern":"writing new config: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/home/config.go","lineNumber":679,"sourceCode":"\t\tDataDir:    filepath.Join(workDir, dataDir),\n\t})\n\n\tvar upgraded bool\n\tconfig.fileData, upgraded, err = migrator.Migrate(\n\t\tctx,\n\t\tconfig.fileData,\n\t\tconfigmigrate.LastSchemaVersion,\n\t)\n\tif err != nil {\n\t\t// Don't wrap the error, because it's informative enough as is.\n\t\treturn err\n\t} else if upgraded {\n\t\tconfPath = configFilePath(ctx, l, workDir, confPath)\n\t\tl.DebugContext(ctx, \"writing config file after config upgrade\", \"path\", confPath)\n\n\t\terr = maybe.WriteFile(confPath, config.fileData, aghos.DefaultPermFile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"writing new config: %w\", err)\n\t\t}\n\t}\n\n\terr = yaml.Unmarshal(config.fileData, &config)\n\tif err != nil {\n\t\t// Don't wrap the error since it's informative enough as is.\n\t\treturn err\n\t}\n\n\terr = validateConfig(ctx, l, config.fileData)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif config.DNS.UpstreamTimeout == 0 {\n\t\tconfig.DNS.UpstreamTimeout = timeutil.Duration(dnsforward.DefaultTimeout)\n\t}\n","sourceCodeStart":661,"sourceCodeEnd":697,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/home/config.go#L661-L697","documentation":"After upgrading the config to a newer schema, AdGuard Home failed to write the migrated config file to disk. The wrapped error is a filesystem error from maybe.WriteFile.","triggerScenarios":"Startup detects the config needs upgrading, writes the new version to confPath, and the OS rejects the write (permissions, missing/invalid directory, disk full, read-only filesystem).","commonSituations":"Running the binary as a non-root user without write access to the config dir, config path pointing to a read-only mount/container, full disk, SELinux/AppArmor denials.","solutions":["Check the wrapped error for the OS-level cause (permission denied, no space, etc.)","Grant write permission on the config directory to the running user (chown/chmod)","Free disk space or remount the filesystem read-write","Verify the -w work-dir / config path is correct for how the service runs"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Preflight: ensure config dir is writable before upgrading\nif f, err := os.CreateTemp(confDir, \".w\"); err != nil { return err } else { f.Close(); os.Remove(f.Name()) }","typeGuard":null,"tryCatchPattern":"// On write failure, keep serving with in-memory config and alert\nif err != nil { log.Error(...); continueWithOldConfig() }","preventionTips":["Run the service as a user with write access to the config dir","Keep the config directory on a writable volume","Back up AdGuardHome.yaml before upgrades"],"tags":["config","filesystem","permissions","startup","upgrade"],"backgroundTag":"config-file-write-failure","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}