{"record":{"id":"de0c8b9f605dc932","repo":"unslothai/unsloth","slug":"fill-absent-fields-cannot-be-combined-with-remove","errorCode":null,"errorMessage":"fill_absent_fields cannot be combined with remove.","messagePattern":"fill_absent_fields cannot be combined with remove\\.","errorType":"exception","errorClass":"ValueError","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/settings.py","lineNumber":1255,"sourceCode":"    def wrapper(*args, **kwargs):\n        with _override_write_lock:\n            return func(*args, **kwargs)\n\n    return wrapper\n\n\n@router.put(\"/openai-auto-switch/overrides\", response_model = ModelOverridesResponse)\n@_serialized_override_write\ndef update_openai_auto_switch_override(\n    payload: ModelOverridePayload, current_subject: str = Depends(get_current_subject)\n) -> ModelOverridesResponse:\n    from core.inference.llama_server_args import drop_managed_flags, validate_extra_args\n    from utils.openai_auto_switch_settings import get_model_override\n\n    try:\n        if payload.fill_absent_fields and payload.remove is True:\n            # A fill that is also a delete has no meaning; picking one loses or resurrects.\n            raise ValueError(\"fill_absent_fields cannot be combined with remove.\")\n        # Only model_id is the documented \"remove\"; otherwise omitted flags carry over.\n        requested_extra_args = payload.llama_extra_args\n        # fill_absent_fields is a write mode, not a saved field: leaving it in would make\n        # every payload look non-empty and break the legacy \"no fields means remove\".\n        saved_fields = payload.model_dump(\n            exclude = {\"model_id\", \"llama_extra_args\", \"remove\", \"fill_absent_fields\"},\n            exclude_none = True,\n        )\n        if payload.remove is not None:\n            is_removal = payload.remove\n        else:\n            is_removal = not payload.tensor_parallel and not {\n                key: value for key, value in saved_fields.items() if key != \"tensor_parallel\"\n            }\n        if requested_extra_args is None and not is_removal:\n            stored = get_model_override(payload.model_id)\n            # A fill keeps the stored flags without echoing them back through validation: one\n            # denylisted since it was saved would 400 the migration, which then retries forever.","sourceCodeStart":1237,"sourceCodeEnd":1273,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/settings.py#L1237-L1273","documentation":"HTTP 409 from PUT /settings/openai-auto-switch/overrides when the payload sets both fill_absent_fields=true and remove=true. The route raises this ValueError deliberately (mapped to 409): a request that simultaneously fills absent fields and deletes the override entry has no coherent meaning — honoring either would silently lose or resurrect settings. It is a request-shape guard, fired before any write happens, so no state changes.","triggerScenarios":"PUT overrides with {model_id, fill_absent_fields: true, remove: true} — e.g. a form that merges 'fill missing fields' and 'delete this entry' checkboxes, or a client that hard-codes remove:true on every save while also passing the fill flag.","commonSituations":"UI mode toggle left on when the user clicks Delete; payloads built by spread of defaults ({...defaults, remove:true}) that inherit fill_absent_fields:true; API wrappers always sending both flags.","solutions":["Pick one mode: to delete, send remove:true (and omit fill_absent_fields or set false); to fill, send fill_absent_fields:true with remove:false/omitted.","In the client, make fill and remove mutually exclusive controls (radio, not checkboxes).","Strip remove from the payload object when the user chose 'fill and save'."],"exampleFix":"// before\nawait api.put('/settings/openai-auto-switch/overrides', { model_id, fill_absent_fields: true, remove: true, ...fields }); // 409\n\n// after\nconst payload = { model_id, ...fields };\nif (mode === 'delete') payload.remove = true;\nelse if (mode === 'fill') payload.fill_absent_fields = true;\nawait api.put('/settings/openai-auto-switch/overrides', payload);","handlingStrategy":"validation","validationCode":"if (payload.fill_absent_fields && payload.remove === true) {\n  throw new Error('Choose fill OR remove, not both');\n}\nawait api.put('/settings/openai-auto-switch/overrides', payload);","typeGuard":"function isCoherentOverridePayload(p: { fill_absent_fields?: boolean; remove?: boolean | null }): boolean {\n  return !(p.fill_absent_fields === true && p.remove === true);\n}","tryCatchPattern":"try { await api.put('/settings/openai-auto-switch/overrides', payload); }\ncatch (e) {\n  if (e.status === 409 && /fill_absent_fields/.test(e.detail)) { delete payload.remove; return api.put(url, payload); }\n  throw e;\n}","preventionTips":["Model fill/remove as mutually exclusive modes (radio buttons) in the UI.","Never spread a defaults object that includes both flags into the request.","Strip the flag that does not apply before serializing the payload."],"tags":["fastapi","http-409","validation","mutually-exclusive","model-overrides"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}