astrid-runtime/astrid · error
InvalidData
InvalidData
Error message
captured Windows descendant has no final component
What it means
This InvalidData error is raised by `TrustedPathGuard::verify` while re-walking the captured component chain: when a component has a parent handle, verify derives its child name with `component.path.file_name()`, and if that returns None the captured component record is malformed — it has no final component to open handle-relatively. This indicates an internal invariant violation in how components were captured, not caller input.
Solutions
- Treat this as a library bug: file an issue with the path passed to capture and the full error message.
- As a workaround, re-create the guard (`TrustedPathGuard::capture`) freshly for the same directory and retry the operation.
- Confirm your path has no trailing separators or root-only segments (`C:\`, `C:\.`) that could produce components without a file_name.
Defensive patterns
Strategy: try-catch
Try / catch
match guard.verify() {
Err(e) if e.kind() == io::ErrorKind::InvalidData
&& e.to_string().contains("no final component") => {
// internal invariant violation: re-capture and retry once, else escalate
let guard = TrustedPathGuard::capture(&boundary)?;
guard.verify()?;
}
other => other?,
} Prevention
- Treat this as a library bug: report it with the capture path and full error text.
- Avoid paths with trailing separators or root-only segments that could produce malformed component records.
- Re-create the guard freshly rather than reusing one that failed verification.
When it happens
Trigger: `verify` (called by `prepare_executable_transaction`, `acquire_named_private_lock`, `stage_transaction_copy_authenticated`, `stage_unique_bytes_with_share`, `verify_contract`) iterating a `LockedPathComponent` whose stored path equals the volume root or a prefix without a final component — i.e. a captured component recorded as the root such that `file_name()` is None while a parent handle exists.
Common situations: Practically only from an internal bug or memory/corruption of the guard: paths like `C:\` being pushed as a non-first component, or a component path rebuilt with normalization that stripped the final name. Users hit it as an opaque failure during transaction staging on Windows.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/81b6e72c1781e76f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-core/src/platform_fs/windows/path.rs:261
// child mutations resolve relative to that boundary handle, so an
// ancestor rename cannot redirect the operation into another tree.
let result = Self {
components,
authority_boundary: path.to_path_buf(),
};
validate_trusted_parent_acl_handle(
result.authority_handle(),
&result.authority_boundary.display().to_string(),
)?;
Ok(result)
}
pub(super) fn verify(&self) -> io::Result<()> {
let mut parent_handle: Option<OwnedHandle> = None;
for component in &self.components {
let (handle, identity) = if let Some(parent) = &parent_handle {
let name = component.path.file_name().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
"captured Windows descendant has no final component",
)
})?;
open_directory_identity_relative(parent.0, name, false)?
} else {
open_directory_identity(&component.path, true)?
};
if identity != component.identity {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!(
"trusted Windows path changed during a security-sensitive operation: {}",
component.path.display()
),
));
}
parent_handle = Some(handle);View on GitHub (pinned to affd8760f4)