Compare commits

...

1 Commits

Author SHA1 Message Date
David Wiesen
41219571b0 Improve Windows sandbox config errors 2026-05-06 10:09:52 -07:00
2 changed files with 45 additions and 1 deletions

View File

@@ -125,15 +125,26 @@ pub fn config_error_from_typed_toml<T: DeserializeOwned>(
.or_else(|| toml_err.span())
.map(|span| text_range_from_span(contents, span))
.unwrap_or_else(default_range);
let message = enrich_config_error_message(path_hint.clone(), toml_err.message());
Some(ConfigError::new(
path.as_ref().to_path_buf(),
range,
toml_err.message(),
message,
))
}
}
}
fn enrich_config_error_message(path: SerdePath, message: String) -> String {
if is_windows_sandbox_mode_path(&path) && message.contains("unknown variant") {
return format!(
"{message}. `[windows].sandbox` only accepts `elevated` or `unelevated`. If you meant WSL2, run Codex inside WSL instead of setting this config value."
);
}
message
}
pub async fn first_layer_config_error<T: DeserializeOwned>(
layers: &ConfigLayerStack,
config_toml_file: &str,
@@ -329,6 +340,13 @@ fn is_features_table_path(path: &SerdePath) -> bool {
&& segments.next().is_none()
}
fn is_windows_sandbox_mode_path(path: &SerdePath) -> bool {
let mut segments = path.iter();
matches!(segments.next(), Some(SerdeSegment::Map { key }) if key == "windows")
&& matches!(segments.next(), Some(SerdeSegment::Map { key }) if key == "sandbox")
&& segments.next().is_none()
}
fn span_for_features_value(contents: &str) -> Option<std::ops::Range<usize>> {
let doc = contents.parse::<Document<String>>().ok()?;
let root = doc.as_item().as_table_like()?;

View File

@@ -245,6 +245,32 @@ fn schema_error_points_to_feature_value() {
assert_eq!(error.range.start.column, value_column);
}
#[test]
fn windows_sandbox_schema_error_includes_wsl_guidance() {
let tmp = tempdir().expect("tempdir");
let contents = "[windows]\nsandbox = \"wsL2\"";
let config_path = tmp.path().join(CONFIG_TOML_FILE);
std::fs::write(&config_path, contents).expect("write config");
let _guard = codex_utils_absolute_path::AbsolutePathBufGuard::new(tmp.path());
let error = codex_config::config_error_from_typed_toml::<ConfigToml>(&config_path, contents)
.expect("schema error");
assert!(
error
.message
.contains("`[windows].sandbox` only accepts `elevated` or `unelevated`"),
"unexpected error: {}",
error.message
);
assert!(
error.message.contains("run Codex inside WSL"),
"unexpected error: {}",
error.message
);
assert_eq!(error.range.start.line, 2);
}
#[tokio::test]
async fn merges_managed_config_layer_on_top() {
let tmp = tempdir().expect("tempdir");