{"record":{"id":"6ce19398b6cd055b","repo":"netbirdio/netbird","slug":"load-config-w","errorCode":null,"errorMessage":"load config: %w","messagePattern":"load config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/android/client.go","lineNumber":302,"sourceCode":"\t\tSearchDomains: strings.Join(searchDomains, \";\"),\n\t}, nil\n}\n\n// DebugBundle generates a debug bundle, uploads it, and returns the upload key.\n// It works both with and without a running engine. anonymizeLevel is \"default\"\n// or \"strict\"; strict also anonymizes internal IP ranges, peer names, and\n// WireGuard public keys, and implies anonymize.\nfunc (c *Client) DebugBundle(platformFiles PlatformFiles, anonymize bool, anonymizeLevel string) (string, error) {\n\tcfg, cacheDir, cc := c.stateSnapshot()\n\n\t// If the engine hasn't been started, load config from disk\n\tif cfg == nil {\n\t\tvar err error\n\t\tcfg, err = profilemanager.UpdateOrCreateConfig(profilemanager.ConfigInput{\n\t\t\tConfigPath: platformFiles.ConfigurationFilePath(),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"load config: %w\", err)\n\t\t}\n\t\tcacheDir = platformFiles.CacheDir()\n\t}\n\n\tdeps := debug.GeneratorDependencies{\n\t\tInternalConfig: cfg,\n\t\tStatusRecorder: c.recorder,\n\t\tTempDir:        cacheDir,\n\t\tStatePath:      platformFiles.StateFilePath(),\n\t}\n\n\tif cc != nil {\n\t\tresp, err := cc.GetLatestSyncResponse()\n\t\tif err != nil {\n\t\t\tlog.Warnf(\"get latest sync response: %v\", err)\n\t\t}\n\t\tdeps.SyncResponse = resp\n","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/android/client.go#L284-L320","documentation":"Android Client.DebugBundle builds a support bundle. If the engine was never started the in-memory state snapshot is empty, so it falls back to profilemanager.UpdateOrCreateConfig to read or create the config at platformFiles.ConfigurationFilePath(); any failure there (unreadable path, unwritable directory, malformed existing file) is wrapped as this error.","triggerScenarios":"Calling DebugBundle before a successful Connect/login on a fresh install; the app lacking storage permission for the config path; a corrupted or partially written config file left by a crash.","commonSituations":"Bug-report button pressed on first launch pre-login; Android scoped-storage revoking access to the chosen directory; config file truncated by a power loss.","solutions":["Call DebugBundle only after a successful connect so the state snapshot exists and no disk load is needed.","Verify the app can read and write platformFiles.ConfigurationFilePath() and its parent directory.","If the existing config is corrupt, remove it so UpdateOrCreateConfig can recreate a default one."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Only offer the debug-bundle action once a config is known to exist\nif _, err := os.Stat(platformFiles.ConfigurationFilePath()); err != nil && !connected {\n    return errors.New(\"connect or log in first; no config to load\")\n}","typeGuard":null,"tryCatchPattern":"path, err := client.DebugBundle(files, true, \"anonymize\")\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"load config:\") {\n        // engine not started AND config unreadable: check permissions,\n        // recreate the config, or debug after a successful connect\n    }\n    return err\n}","preventionTips":["Gate the debug-bundle UI on connection state so the fast in-memory snapshot path is used.","Ensure the app holds storage permission for the config directory.","Regenerate a corrupt config instead of retrying DebugBundle against a broken file."],"tags":["android","debug","configuration","file-io"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}