{"record":{"id":"d8206d8ef86ea856","repo":"clash-verge-rev/clash-verge-rev","slug":"file-field-is-required-when-file-data-is-provided","errorCode":null,"errorMessage":"file field is required when file_data is provided","messagePattern":"file field is required when file_data is provided","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/config/profiles.rs","lineNumber":222,"sourceCode":"    /// if the file_data is some\n    /// then should save the data to file\n    pub async fn append_item(&mut self, item: &mut PrfItem) -> Result<()> {\n        let uid = &item.uid;\n        if uid.is_none() {\n            bail!(\"the uid should not be null\");\n        }\n\n        // save the file data\n        // move the field value after save\n        if let Some(file_data) = item.file_data.take() {\n            if item.file.is_none() {\n                bail!(\"the file should not be null\");\n            }\n\n            let file = item\n                .file\n                .clone()\n                .ok_or_else(|| anyhow::anyhow!(\"file field is required when file_data is provided\"))?;\n            let path = dirs::app_profiles_dir()?.join(file.as_str());\n\n            fs::write(&path, file_data.as_bytes())\n                .await\n                .with_context(|| format!(\"failed to write to file \\\"{file}\\\"\"))?;\n        }\n\n        if self.current.is_none() && (item.itype == Some(\"remote\".into()) || item.itype == Some(\"local\".into())) {\n            self.current = uid.to_owned();\n        }\n\n        if self.items.is_none() {\n            self.items = Some(vec![]);\n        }\n\n        if let Some(items) = self.items.as_mut() {\n            items.push(item.to_owned());\n        }","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/clash-verge-rev/clash-verge-rev/blob/5cad0f2799e74b1105e133bcfc2a45f5c1370ef1/src-tauri/src/config/profiles.rs#L204-L240","documentation":"Thrown by IProfiles::append_item when a PrfItem carries `file_data` (inline content to be written to disk) but the `file` field (the destination filename) is None. The preceding `bail!` covers the same case with a different message; this `ok_or_else` is the fall-through guard after the `bail!` branch is logically unreachable. Together they enforce the invariant that inline file data must name a target file.","triggerScenarios":"Constructing a PrfItem programmatically and setting `file_data` without setting `file`; deserializing a profile item from JSON/Tauri command payload that includes file_data but omits or nulls the file field.","commonSituations":"Frontend sends a 'create local profile' payload with the raw YAML content but forgets to send the filename; a migration script copies file_data between items but drops the file field; a test fixture builds a PrfItem incompletely.","solutions":["Set `item.file` to a valid filename (e.g. the uid + `.yaml`) whenever `item.file_data` is `Some`.","Validate the payload on the Tauri command boundary before calling append_item, rejecting items where file_data is present but file is absent.","If importing programmatically, derive the filename from the uid when it is missing."],"exampleFix":"// before\nitem.file_data = Some(yaml.to_string());\n// item.file left as None\n// after\nitem.file = Some(format!(\"{}.yaml\", uid));\nitem.file_data = Some(yaml.to_string());","handlingStrategy":"validation","validationCode":"fn validate_item(item: &PrfItem) -> Result<(), String> {\n    if item.file_data.is_some() && item.file.is_none() {\n        return Err(\"file field is required when file_data is provided\".into());\n    }\n    Ok(())\n}","typeGuard":"fn item_is_well_formed(item: &PrfItem) -> bool {\n    !(item.file_data.is_some() && item.file.is_none())\n}","tryCatchPattern":"if let Err(e) = profiles.append_item(&mut item).await {\n    if e.to_string().contains(\"file field is required\") {\n        // surface to UI: ask user for filename or derive from uid\n    }\n}","preventionTips":["On the Tauri command boundary, reject payloads where file_data is set but file is absent.","Derive item.file from item.uid at construction time when importing local content.","Add a unit test that asserts append_item errors on file_data-without-file."],"tags":["profiles","validation","invariant","config"],"analyzedSha":"5cad0f2799e74b1105e133bcfc2a45f5c1370ef1","analyzedAt":"2026-08-12T03:25:57.699Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}