@@ -117,32 +117,90 @@ void ModelManager::scanDirectoryInternal(const std::string& directory, ModelType
117117 }
118118
119119 std::vector<ModelInfo> found_models;
120+ int processed_count = 0 ;
120121
121122 try {
122- for (const auto & entry : fs::recursive_directory_iterator (directory)) {
123- if (!entry.is_regular_file ()) {
123+ // Use error_code overload to prevent exceptions from blocking iteration
124+ std::error_code ec;
125+ fs::recursive_directory_iterator it (directory, fs::directory_options::skip_permission_denied, ec);
126+
127+ if (ec) {
128+ LOG_ERROR (" Cannot create directory iterator for %s: %s" , directory.c_str (), ec.message ().c_str ());
129+ return ;
130+ }
131+
132+ for (const auto & entry : it) {
133+ processed_count++;
134+
135+ // Log progress every 50 files for user feedback
136+ if (processed_count % 50 == 0 ) {
137+ LOG_INFO (" Scanning %s directory: processed %d files..." , getModelTypeString (type).c_str (),
138+ processed_count);
139+ }
140+
141+ // Skip non-regular files with error handling
142+ std::error_code file_ec;
143+ bool is_regular = entry.is_regular_file (file_ec);
144+ if (file_ec || !is_regular) {
145+ if (file_ec) {
146+ LOG_VERBOSE (" Skipping entry (cannot determine file type): %s" , entry.path ().string ().c_str ());
147+ }
124148 continue ;
125149 }
126150
127- std::string filename = entry.path ().filename ().string ();
151+ // Try to get the path strings - use generic_string() for better Unicode support
152+ std::string filename;
153+ std::string full_path;
154+ try {
155+ // generic_string() handles Unicode better than string() on Windows
156+ filename = entry.path ().filename ().generic_string ();
157+ full_path = entry.path ().generic_string ();
158+ } catch (const std::exception& e) {
159+ // Fallback to regular string() if generic_string() fails
160+ try {
161+ filename = entry.path ().filename ().string ();
162+ full_path = entry.path ().string ();
163+ LOG_VERBOSE (" Using string() for path: %s" , filename.c_str ());
164+ } catch (...) {
165+ LOG_WARNING (" Cannot convert path to string, skipping file: %s" , e.what ());
166+ continue ;
167+ }
168+ }
169+
128170 if (!isValidModelFile (filename)) {
129171 continue ;
130172 }
131173
132- std::string full_path = entry.path ().string ();
133- size_t file_size = fs::file_size (entry.path ());
174+ // Get file size with error handling - don't let this block the scan
175+ size_t file_size = 0 ;
176+ try {
177+ file_size = fs::file_size (entry.path (), file_ec);
178+ if (file_ec) {
179+ LOG_VERBOSE (" Cannot get file size for %s: %s, using 0" , filename.c_str (),
180+ file_ec.message ().c_str ());
181+ file_size = 0 ;
182+ }
183+ } catch (const std::exception& e) {
184+ LOG_VERBOSE (" Cannot get file size for %s: %s, using 0" , filename.c_str (), e.what ());
185+ file_size = 0 ;
186+ }
134187
135188 // Determine the lookup name based on model type
136189 std::string lookup_name;
137- if (type == ModelType::CHECKPOINT) {
138- // For stable-diffusion models: use relative path from directory with extension
139- fs::path relative = fs::relative (entry.path (), directory);
140- lookup_name = relative.string ();
141- } else if (type == ModelType::CONTROLNET || type == ModelType::EMBEDDINGS || type == ModelType::LORA) {
142- // For controlnet, embeddings, lora: use filename without extension
143- lookup_name = entry.path ().stem ().string ();
144- } else {
145- // For other model types: use filename as-is
190+ try {
191+ if (type == ModelType::CHECKPOINT) {
192+ // For stable-diffusion models: use relative path from directory with extension
193+ fs::path relative = fs::relative (entry.path (), directory);
194+ lookup_name = relative.string ();
195+ } else if (type == ModelType::CONTROLNET || type == ModelType::EMBEDDINGS || type == ModelType::LORA) {
196+ // For controlnet, embeddings, lora: use filename without extension
197+ lookup_name = entry.path ().stem ().string ();
198+ } else {
199+ // For other model types: use filename as-is
200+ lookup_name = filename;
201+ }
202+ } catch (const std::exception& e) {
203+ LOG_WARNING (" Cannot process path for %s: %s, using filename" , filename.c_str (), e.what ());
146204 lookup_name = filename;
147205 }
148206
@@ -155,6 +213,9 @@ void ModelManager::scanDirectoryInternal(const std::string& directory, ModelType
155213 } catch (const fs::filesystem_error& e) {
156214 LOG_ERROR (" Error scanning directory %s: %s" , directory.c_str (), e.what ());
157215 return ;
216+ } catch (const std::exception& e) {
217+ LOG_ERROR (" Unexpected error scanning directory %s: %s" , directory.c_str (), e.what ());
218+ return ;
158219 }
159220
160221 // Update the models_ map (already locked by caller)
0 commit comments