Skip to content

Commit cbdf85c

Browse files
committed
Fix crash on startup thanks to invalid default profile & auto connect
See OctoPrint#1942 This does NOT fix the root cause of `_default.profile` becoming an empty file (apparently during migration from config.yaml?), however since this particular situation was impossible to reproduce so far this workaround for the consequences will have to suffice for now since we want a hotfix as fast as possible for 1.3.3.
1 parent b55c4ef commit cbdf85c

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

src/octoprint/printer/profile.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,33 +215,55 @@ def _migrate_old_default_profile(self):
215215
if self.exists("_default"):
216216
return
217217

218+
if not isinstance(default_overrides, dict):
219+
self._logger.warn("Existing default profile from settings is not a valid profile, refusing to migrate: {!r}".format(default_overrides))
220+
return
221+
218222
default_overrides["id"] = "_default"
219223
self.save(default_overrides)
220224

221225
settings().set(["printerProfiles", "defaultProfile"], None)
222226
settings().save()
223227

228+
self._logger.info("Migrated default printer profile from settings to _default.profile: {!r}".format(default_overrides))
229+
224230
def _verify_default_available(self):
225231
default_id = settings().get(["printerProfile", "default"])
226232
if default_id is None:
227233
default_id = "_default"
228234

229235
if not self.exists(default_id):
230236
if not self.exists("_default"):
231-
self._logger.error("Selected default profile {} and _default do not exist, creating _default again and setting it as default".format(default_id))
237+
if default_id == "_default":
238+
self._logger.error("Profile _default does not exist, creating _default again and setting it as default")
239+
else:
240+
self._logger.error("Selected default profile {} and _default do not exist, creating _default again and setting it as default".format(default_id))
232241
self.save(self.__class__.default, allow_overwrite=True, make_default=True)
233242
else:
234243
self._logger.error("Selected default profile {} does not exists, resetting to _default".format(default_id))
235244
settings().set(["printerProfiles", "default"], "_default")
236245
settings().save()
246+
default_id = "_default"
247+
248+
profile = self.get(default_id)
249+
if profile is None:
250+
self._logger.error("Selected default profile {} is invalid, resetting to default values".format(default_id))
251+
profile = copy.deepcopy(self.__class__.default)
252+
profile["id"] = default_id
253+
self.save(self.__class__.default, allow_overwrite=True, make_default=True)
237254

238255
def select(self, identifier):
239256
if identifier is None or not self.exists(identifier):
240257
self._current = self.get_default()
241258
return False
242259
else:
243260
self._current = self.get(identifier)
244-
return True
261+
if self._current is None:
262+
self._logger.error("Profile {} is invalid, cannot select, falling back to default".format(identifier))
263+
self._current = self.get_default()
264+
return False
265+
else:
266+
return True
245267

246268
def deselect(self):
247269
self._current = None
@@ -310,6 +332,8 @@ def get_default(self):
310332
profile = self.get(default)
311333
if profile is not None:
312334
return profile
335+
else:
336+
self._logger.warn("Default profile {} is invalid, falling back to built-in defaults".format(default))
313337

314338
return copy.deepcopy(self.__class__.default)
315339

@@ -344,6 +368,7 @@ def _load_all(self):
344368
try:
345369
profile = self._load_from_path(path)
346370
except InvalidProfileError:
371+
self._logger.warn("Profile {} is invalid, skipping".format(identifier))
347372
continue
348373

349374
if profile is None:
@@ -373,6 +398,9 @@ def _load_from_path(self, path):
373398
with open(path) as f:
374399
profile = yaml.safe_load(f)
375400

401+
if profile is None or not isinstance(profile, dict):
402+
raise InvalidProfileError("Profile is None or not a dictionary")
403+
376404
if self._migrate_profile(profile):
377405
try:
378406
self._save_to_path(path, profile, allow_overwrite=True)

src/octoprint/server/__init__.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -475,11 +475,14 @@ def joined_dict(*dicts):
475475

476476
# auto connect
477477
if self._settings.getBoolean(["serial", "autoconnect"]):
478-
(port, baudrate) = self._settings.get(["serial", "port"]), self._settings.getInt(["serial", "baudrate"])
479-
printer_profile = printerProfileManager.get_default()
480-
connectionOptions = printer.__class__.get_connection_options()
481-
if port in connectionOptions["ports"]:
482-
printer.connect(port=port, baudrate=baudrate, profile=printer_profile["id"] if "id" in printer_profile else "_default")
478+
try:
479+
(port, baudrate) = self._settings.get(["serial", "port"]), self._settings.getInt(["serial", "baudrate"])
480+
printer_profile = printerProfileManager.get_default()
481+
connectionOptions = printer.__class__.get_connection_options()
482+
if port in connectionOptions["ports"]:
483+
printer.connect(port=port, baudrate=baudrate, profile=printer_profile["id"] if "id" in printer_profile else "_default")
484+
except:
485+
self._logger.exception("Something went wrong while attempting to automatically connect to the printer")
483486

484487
# start up watchdogs
485488
if self._settings.getBoolean(["feature", "pollWatched"]):

0 commit comments

Comments
 (0)