libnyanpasu/clash-nyanpasu · error · anyhow::Error
child process failed: {:?}, err: {}
Error message
child process failed: {:?}, err: {} What it means
run_pending_migrations runs a child process (migration sidecar) and waits for it. If the child exits with a non-zero status code, this anyhow error is raised wrapping the exit status and any collected stderr/stdout error strings from the child. It signals that a migration step did not complete successfully.
Source
Thrown at backend/tauri/src/utils/init/mod.rs:93
errs.push_str(unsafe { std::str::from_utf8_unchecked(&buf) });
}
Err(e) => {
eprintln!("failed to read stderr: {e:?}");
let mut errs = errs_.lock();
errs.push_str(&format!("failed to read stderr: {e:?}\n"));
break;
}
}
}
});
let result = child.wait();
let _l = guard.write(); // Just for waiting the thread read all the output
let err = errs.lock();
result
.map_err(|e| anyhow!("Failed to wait for child: {:?}, errs: {}", e, err))
.and_then(|status| {
if !status.success() {
Err(anyhow!("child process failed: {:?}, err: {}", status, err))
} else {
Ok(())
}
})
}
/// Initialize all the config files
/// before tauri setup
pub fn init_config() -> Result<()> {
// Check if old config dir exist and new config dir is not exist
// let mut old_app_dir: Option<PathBuf> = None;
// let mut app_dir: Option<PathBuf> = None;
// crate::dialog_err!(dirs::old_app_home_dir().map(|_old_app_dir| {
// old_app_dir = Some(_old_app_dir);
// }));
// crate::dialog_err!(dirs::app_home_dir().map(|_app_dir| {
// app_dir = Some(_app_dir);View on GitHub (pinned to f7dbce2997)
Solutions
- Read the captured child output (the `errs` content) in the error message to find the migration's own failure reason
- Verify the migration sidecar binary exists and is executable (re-run pnpm prepare:check or reinstall)
- Check permissions and free disk space on the app data directory
- Fix or roll back the failing migration; if caused by a code change, run the migration binary manually to reproduce
- Retry startup once the underlying cause is fixed
Example fix
// before: opaque failure
Err(anyhow!("child process failed: {:?}, err: {}", status, err))
// after: also surface captured child output
let out = out_log.lock().join("\n");
Err(anyhow!("child process failed: {:?}, err: {}, output: {}", status, err, out)) Defensive patterns
Strategy: try-catch
Validate before calling
let status = cmd.status()?;
if !status.success() { bail!("migration sidecar unavailable (exit {})", status); } Try / catch
match run_pending_migrations().await {
Ok(()) => {},
Err(e) => {
log::error!("migrations failed: {e:#}");
// block startup or show recovery UI
}
} Prevention
- Keep the migration sidecar in sync with the app version (prepare:check)
- Capture and include child stdout/stderr in error messages
- Test migrations against a copy of a real user data directory
- Check disk space and permissions before spawning
When it happens
Trigger: Calling run_pending_migrations when the spawned child process exits with status.success() == false, e.g. the migration binary crashes or returns a failure exit code.
Common situations: Corrupt or incompatible app data directory blocking migrations; a missing/broken sidecar binary; migration script bug; insufficient permissions on the data directory; disk full.
Related errors
- {operation} failed with status {status}
- Failed to wait for child: {:?}, errs: {}
- failed to get core version
- {stderr}
- cannot repair typed clash config before split_legacy_config
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/9f4fb78d9b7c7b92.
Report an issue: GitHub.