{"record":{"id":"59c84d84b6de9a7e","repo":"ramensoftware/windhawk","slug":"throw-portablesettingsexception-error","errorCode":null,"errorMessage":"throw PortableSettingsException(error)","messagePattern":"throw PortableSettingsException\\(error\\)","errorType":"exception","errorClass":"PortableSettingsException","httpStatus":null,"severity":"error","filePath":"src/windhawk/shared/portable_settings.cpp","lineNumber":10,"sourceCode":"#include \"stdafx.h\"\n\n#include \"portable_settings.h\"\n\n// Use WIL to throw exceptions if possible.\n#ifdef THROW_WIN32\n#define PORTABLE_SETTINGS_THROW_WIN32(error) THROW_WIN32(error)\n#else\n#define PORTABLE_SETTINGS_THROW_WIN32(error) \\\n    throw PortableSettingsException(error)\n#endif\n\n////////////////////////////////////////////////////////////////////////////////\n// EnumIteratorImpl\n\ntemplate <typename Type>\nclass EnumIteratorImpl {\n   public:\n    bool is_done() const { return done; }\n\n    const std::pair<std::wstring, Type>& get_item() const { return item; }\n\n    virtual void next() = 0;\n    virtual std::unique_ptr<EnumIteratorImpl> clone() const = 0;\n    virtual ~EnumIteratorImpl() = default;\n\n   protected:\n    EnumIteratorImpl() = default;","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/ramensoftware/windhawk/blob/61d99ed8e182e1af1b60109612b6763ad1b4b74e/src/windhawk/shared/portable_settings.cpp#L1-L28","documentation":"portable_settings.cpp defines PortableSettingsException as the throw mechanism for Win32 errors encountered by the portable-settings component. When WIL's THROW_WIN32 is unavailable, PORTABLE_SETTINGS_THROW_WIN32(error) throws PortableSettingsException(error) wrapping the Win32 error code, so callers get an exception carrying the exact GetLastError value from settings file/directory operations.","triggerScenarios":"A Win32 call inside portable settings (creating/opening the settings file or directory, reading/writing configuration) fails and the failure path expands to throw PortableSettingsException(GetLastError-derived error).","commonSituations":"Settings directory not writable (access denied), portable-mode path on a read-only or missing drive, file locked by another process, or disk full while persisting settings.","solutions":["Check the wrapped Win32 error code in the exception to identify the exact OS failure.","Ensure the portable settings directory exists and is writable by the running user (fix ACLs or move the portable path off read-only media).","Close other processes locking the settings file, or retry after the lock is released.","Verify the portable flag/path configuration points at a valid location before launch."],"exampleFix":"// before (C++ caller, no handling)\nPortableLoadSettings(path);\n// after\ntry { PortableLoadSettings(path); }\ncatch (const PortableSettingsException& e) {\n    LOG(\"portable settings failed: %u\", e.GetError());\n    // fall back to defaults or a writable path\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    PortableLoadSettings();\n}\ncatch (const PortableSettingsException& e)\n{\n    switch (e.GetError())\n    {\n    case ERROR_ACCESS_DENIED: /* fix ACLs / run elevated */ break;\n    case ERROR_FILE_NOT_FOUND: /* fall back to defaults */ break;\n    default: LOG(\"portable settings error %u\", e.GetError()); break;\n    }\n}","preventionTips":["Verify the portable settings directory exists and is writable before launch.","Don't place the portable path on read-only or removable media.","Avoid concurrent processes writing the same settings file.","Check free disk space before settings writes."],"tags":["cpp","windows","settings","win32","portable-mode"],"backgroundTag":"win32-error-thrown","analyzedSha":"61d99ed8e182e1af1b60109612b6763ad1b4b74e","analyzedAt":"2026-09-12T14:02:41.115Z","contentChangedAt":"2026-09-12T14:02:41.115Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}