diff --git a/codex-rs/app-server/src/config_manager_service.rs b/codex-rs/app-server/src/config_manager_service.rs index ec4a1a680..aef4393a0 100644 --- a/codex-rs/app-server/src/config_manager_service.rs +++ b/codex-rs/app-server/src/config_manager_service.rs @@ -244,10 +244,6 @@ impl ConfigManager { apply_merge(&mut user_config, &segments, parsed_value.as_ref(), strategy).map_err( |err| match err { - MergeError::PathNotFound => ConfigManagerError::write( - ConfigWriteErrorCode::ConfigPathNotFound, - "Path not found", - ), MergeError::Validation(message) => ConfigManagerError::write( ConfigWriteErrorCode::ConfigValidationError, message, @@ -413,7 +409,6 @@ fn parse_key_path(path: &str) -> Result, String> { #[derive(Debug)] enum MergeError { - PathNotFound, Validation(String), } @@ -485,14 +480,17 @@ fn clear_path(root: &mut TomlValue, segments: &[String]) -> Result { - current = table.get_mut(segment).ok_or(MergeError::PathNotFound)?; + let Some(next) = table.get_mut(segment) else { + return Ok(false); + }; + current = next; } - _ => return Err(MergeError::PathNotFound), + _ => return Ok(false), } } let Some(parent) = current.as_table_mut() else { - return Err(MergeError::PathNotFound); + return Ok(false); }; Ok(parent.remove(last).is_some()) diff --git a/codex-rs/app-server/src/config_manager_service_tests.rs b/codex-rs/app-server/src/config_manager_service_tests.rs index 108254859..e9b0b3c76 100644 --- a/codex-rs/app-server/src/config_manager_service_tests.rs +++ b/codex-rs/app-server/src/config_manager_service_tests.rs @@ -106,6 +106,30 @@ personality = true Ok(()) } +#[tokio::test] +async fn clear_missing_nested_config_is_noop() -> Result<()> { + let tmp = tempdir().expect("tempdir"); + let path = tmp.path().join(CONFIG_TOML_FILE); + std::fs::write(&path, "")?; + + let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf()); + let response = service + .write_value(ConfigValueWriteParams { + file_path: Some(path.display().to_string()), + key_path: "features.personality".to_string(), + value: serde_json::Value::Null, + merge_strategy: MergeStrategy::Replace, + expected_version: None, + }) + .await + .expect("clear missing config succeeds"); + + assert_eq!(response.status, WriteStatus::Ok); + assert_eq!(response.overridden_metadata, None); + assert_eq!(std::fs::read_to_string(&path)?, ""); + Ok(()) +} + #[tokio::test] async fn write_value_supports_nested_app_paths() -> Result<()> { let tmp = tempdir().expect("tempdir");