fix: classify file content conflicts as retryable

This commit is contained in:
2026-09-17 02:54:37 +09:00
parent bc0342b03e
commit 360387c986
6 changed files with 128 additions and 12 deletions
+7 -2
View File
@@ -298,7 +298,12 @@ mod tests {
.execute(&inp.to_string(), Default::default())
.await
.unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("modified externally"), "{msg}");
match err {
ToolError::ExecutionFailed(message) => assert_eq!(
message,
"The target file's content or existence changed since it was last observed; read the file again before retrying: a.txt"
),
other => panic!("expected execution failure, got {other:?}"),
}
}
}
+47 -1
View File
@@ -43,7 +43,8 @@ impl From<ToolsError> for ToolError {
| workdir::WorkdirError::Io { .. }
| workdir::WorkdirError::Unavailable(_)
| workdir::WorkdirError::OperationFailed
| workdir::WorkdirError::Transport(_),
| workdir::WorkdirError::Transport(_)
| workdir::WorkdirError::Conflict(_),
) => ToolError::ExecutionFailed(err.to_string()),
ToolsError::FileSystem(_)
| ToolsError::WorkdirSession(_)
@@ -55,3 +56,48 @@ impl From<ToolsError> for ToolError {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use workdir::http::{WorkdirTransportError, WorkdirTransportErrorCode};
#[test]
fn local_workdir_content_conflict_is_retryable_execution_failure() {
let error = ToolError::from(ToolsError::WorkdirSession(
fs_operation::FsError::Conflict("src/main.rs".to_string()).into(),
));
match error {
ToolError::ExecutionFailed(message) => assert_eq!(
message,
"The target file's content or existence changed since it was last observed; read the file again before retrying: src/main.rs"
),
other => panic!("expected execution failure, got {other:?}"),
}
}
#[test]
fn remote_workdir_content_conflict_is_retryable_without_host_path() {
let transport = WorkdirTransportError::from_workdir_error(
&workdir::WorkdirError::Conflict("/runtime/private/checkout/src/main.rs".to_string()),
);
assert_eq!(transport.code, WorkdirTransportErrorCode::Conflict);
assert_eq!(
transport.message,
"The target file's content or existence changed since it was last observed; read the file again before retrying"
);
let error = ToolError::from(ToolsError::WorkdirSession(transport.into_workdir_error()));
match error {
ToolError::ExecutionFailed(message) => {
assert_eq!(
message,
"The target file's content or existence changed since it was last observed; read the file again before retrying"
);
assert!(!message.contains("/runtime/private"));
}
other => panic!("expected execution failure, got {other:?}"),
}
}
}
+7 -2
View File
@@ -219,8 +219,13 @@ mod tests {
)
.await
.unwrap_err();
let msg = format!("{err}");
assert!(msg.contains("modified externally"), "{msg}");
match err {
ToolError::ExecutionFailed(message) => assert_eq!(
message,
"The target file's content or existence changed since it was last observed; read the file again before retrying: a.txt"
),
other => panic!("expected execution failure, got {other:?}"),
}
}
#[tokio::test]