unslothai/unsloth · error · CorruptSettingsError
Cannot apply partial settings patch to corrupt key(s): {keys
Error message
Cannot apply partial settings patch to corrupt key(s): {keys} What it means
CorruptSettingsError raised by the chat settings merge path when a partial (dict-valued) update targets a key whose stored row has been quarantined as corrupt. A corrupt row has no trustworthy base to deep-merge into, so a partial patch is refused; only atomic keys (members of _ATOMIC_SETTING_KEYS) or full-value replacements are allowed because they overwrite the whole row and effectively repair it. The transaction is committed (releasing the IMMEDIATE lock) before raising.
Source
Thrown at studio/backend/storage/studio_db.py:3692
"""Atomic read-merge-write under BEGIN IMMEDIATE so concurrent writers
cannot drop each other's updates."""
if not updates:
return list_chat_settings()
conn = get_connection()
try:
conn.execute("BEGIN IMMEDIATE")
current, corrupt = _load_chat_settings_for_merge(conn)
# An atomic key carries its whole value, so it repairs a quarantined row
# rather than patching a base that is no longer there.
unsafe_partial_keys = [
key
for key, value in updates.items()
if key in corrupt and isinstance(value, dict) and key not in _ATOMIC_SETTING_KEYS
]
if unsafe_partial_keys:
conn.commit()
keys = ", ".join(sorted(unsafe_partial_keys))
raise CorruptSettingsError(
f"Cannot apply partial settings patch to corrupt key(s): {keys}"
)
merged = _deep_merge_settings(current, updates)
now = datetime.now(timezone.utc).isoformat()
conn.executemany(
"""
INSERT INTO chat_settings (key, value_json, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(key) DO UPDATE SET
value_json = excluded.value_json,
updated_at = excluded.updated_at
""",
[(key, json.dumps(value), now) for key, value in merged.items()],
)
conn.commit()
return merged
except CorruptSettingsError:
raiseView on GitHub (pinned to 203007d190)
Solutions
- Send the FULL value for the corrupt key(s) instead of a partial dict, which replaces and repairs the quarantined row
- Delete/reset the corrupt setting row so the next merge starts from a clean base
- Inspect the quarantined keys (the error message lists them) and decide per key whether to restore defaults or write a complete replacement
Example fix
// before (partial patch on a corrupt key -> raises)
update_chat_settings({'training_defaults': {'lr': 1e-4}})
// after (full replacement repairs the row)
update_chat_settings({'training_defaults': {'lr': 1e-4, 'epochs': 3, 'batch': 8}}) Defensive patterns
Strategy: try-catch
Validate before calling
def is_safe_patch(updates: dict, atomic_keys: set[str]) -> bool:
"""A patch is safe if no dict-valued update targets a non-atomic key.
(Corrupt-key awareness lives server-side; this is the structural guard.)"""
return all(
not isinstance(v, dict) or k in atomic_keys
for k, v in updates.items()
) Try / catch
from studio.backend.storage.studio_db import CorruptSettingsError
try:
update_chat_settings(updates)
except CorruptSettingsError as e:
# e names the corrupt keys; re-send FULL values for those keys to repair
corrupt = parse_keys_from_message(str(e))
update_chat_settings({k: full_defaults[k] for k in corrupt})
update_chat_settings(updates) Prevention
- Send whole values (not partial dicts) for settings that may have been quarantined
- After any crash during a settings write, check for quarantined keys before the next save
- Log the key list from the error message — it tells you exactly which rows to repair or reset
When it happens
Trigger: Calling update_chat_settings(updates={'someNestedSetting': {'a': 1}}) where 'someNestedSetting' is currently flagged corrupt by _load_chat_settings_for_merge() and is not in _ATOMIC_SETTING_KEYS.
Common situations: A settings row was corrupted by a crash mid-write or hand-edited JSON; afterwards every partial settings save from the UI fails until the key is reset or sent whole. Common after DB migration bugs or disk-full events during a previous write.
Related errors
- RAG is unavailable: the sqlite-vec extension could not be lo
- Unsupported file type '{ext}'. Allowed: {sorted(config.UPLOA
- File exceeds the {cap // (1024 * 1024)} MB upload limit.
- Uploaded file is empty.
- Native path grant is required.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/3eba6870213c20ed.
Report an issue: GitHub.