Skip to content

Commit 5d5b618

Browse files
committed
v7.0.15: Better error info on remote job failures
- Display exit code, stderr, logs, and stdout when remote jobs fail - Show troubleshooting guidance when no detailed error info available - Add warning when ALL tables are marked schema-only (no data transfer) - Add stdout, stderr, logs, exit_code fields to JobStatus model
1 parent dafd96a commit 5d5b618

6 files changed

Lines changed: 101 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [7.0.15] - 2025-12-31
6+
7+
### Fixed
8+
9+
- **Better error information on remote job failures**: When a remote replication job fails, the CLI now displays exit code, stderr, logs, and stdout (if returned by the API). When no detailed error info is available, provides troubleshooting guidance including common causes and suggests running with `--local` to debug.
10+
11+
### Added
12+
13+
- **Warning when all tables are schema-only**: Interactive mode now warns users when ALL selected tables are marked as schema-only (no data transfer). This prevents accidental configurations where users expect data to be replicated but only schema structures are transferred.
14+
15+
- **Extended JobStatus fields**: Added `stdout`, `stderr`, `logs`, and `exit_code` fields to capture detailed error information from remote job execution.
16+
517
## [7.0.12] - 2025-12-11
618

719
## [7.0.14] - 2025-12-11

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77

88
[package]
99
name = "database-replicator"
10-
version = "7.0.14"
10+
version = "7.0.15"
1111
edition = "2021"
1212
license = "Apache-2.0"
1313
description = "Universal database-to-PostgreSQL replication CLI. Supports PostgreSQL, SQLite, MongoDB, and MySQL."

src/interactive.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,18 @@ pub async fn select_databases_and_tables(
741741
println!("───────────────────────────────────────────────────────────────");
742742
println!();
743743

744+
// Warn if ALL tables are schema-only (no data will be transferred)
745+
let total_tables: usize = included_tables_by_db.values().map(|v| v.len()).sum();
746+
if schema_only_count > 0 && schema_only_count == total_tables {
747+
println!(
748+
"⚠️ WARNING: ALL {} tables are marked as schema-only!",
749+
total_tables
750+
);
751+
println!(" This means NO DATA will be transferred - only table structures.");
752+
println!(" If this is unintentional, press Esc to go back and adjust.");
753+
println!();
754+
}
755+
744756
let confirmed = Confirm::new("Proceed with this configuration?")
745757
.with_default(true)
746758
.with_help_message("Enter confirm, Esc go back")

src/main.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,8 +1172,75 @@ async fn init_remote(
11721172
"failed" => {
11731173
let error_msg = final_status
11741174
.error
1175+
.clone()
11751176
.unwrap_or_else(|| "Unknown error".to_string());
11761177
println!("\n✗ Replication failed: {}", error_msg);
1178+
1179+
// Display exit code if available
1180+
if let Some(exit_code) = final_status.exit_code {
1181+
println!("Exit code: {}", exit_code);
1182+
}
1183+
1184+
// Display stderr if available
1185+
if let Some(ref stderr) = final_status.stderr {
1186+
if !stderr.is_empty() {
1187+
println!("\n--- stderr ---");
1188+
println!("{}", stderr);
1189+
}
1190+
}
1191+
1192+
// Display recent logs if available
1193+
if let Some(ref logs) = final_status.logs {
1194+
if !logs.is_empty() {
1195+
println!("\n--- Recent logs ---");
1196+
for line in logs.iter().take(50) {
1197+
println!("{}", line);
1198+
}
1199+
}
1200+
}
1201+
1202+
// Display stdout if available and stderr wasn't shown
1203+
if final_status.stderr.is_none()
1204+
|| final_status
1205+
.stderr
1206+
.as_ref()
1207+
.map(|s| s.is_empty())
1208+
.unwrap_or(true)
1209+
{
1210+
if let Some(ref stdout) = final_status.stdout {
1211+
if !stdout.is_empty() {
1212+
println!("\n--- stdout ---");
1213+
// Show last 100 lines of stdout
1214+
let lines: Vec<&str> = stdout.lines().collect();
1215+
let start = if lines.len() > 100 {
1216+
lines.len() - 100
1217+
} else {
1218+
0
1219+
};
1220+
for line in &lines[start..] {
1221+
println!("{}", line);
1222+
}
1223+
}
1224+
}
1225+
}
1226+
1227+
// Provide guidance for common issues
1228+
if error_msg.contains("exit code 1")
1229+
&& final_status.logs.is_none()
1230+
&& final_status.stderr.is_none()
1231+
{
1232+
println!("\n--- Troubleshooting ---");
1233+
println!("The remote job failed but no detailed error information is available.");
1234+
println!("Common causes:");
1235+
println!(" • Database connection issues (firewall, credentials, SSL)");
1236+
println!(" • Permission errors on source or target database");
1237+
println!(" • Schema conflicts or constraint violations");
1238+
println!(" • Out of memory on the worker instance");
1239+
println!("\nTo debug locally, run with --local:");
1240+
println!(" database-replicator init --source <source> --target <target> --local");
1241+
println!("\nContact support with job ID: {}", final_status.job_id);
1242+
}
1243+
11771244
anyhow::bail!("Replication failed");
11781245
}
11791246
_ => {

src/remote/models.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ pub struct JobStatus {
4848
pub completed_at: Option<String>,
4949
pub progress: Option<ProgressInfo>,
5050
pub error: Option<String>,
51+
/// Stdout from the replication command (if available)
52+
pub stdout: Option<String>,
53+
/// Stderr from the replication command (if available)
54+
pub stderr: Option<String>,
55+
/// Recent log lines from the job execution
56+
pub logs: Option<Vec<String>>,
57+
/// Exit code from the replication command (if available)
58+
pub exit_code: Option<i32>,
5159
}
5260

5361
#[derive(Debug, Clone, Deserialize)]

0 commit comments

Comments
 (0)