{"record":{"id":"7a00684b1ea2acda","repo":"gitbutlerapp/gitbutler","slug":"archive-progress-counter-thread-panicked","errorCode":null,"errorMessage":"Archive progress counter thread panicked","messagePattern":"Archive progress counter thread panicked","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-debug/src/command/dump/mod.rs","lineNumber":106,"sourceCode":"                    repo_args.git_only,\n                    diagnostics_files,\n                    progress,\n                )\n            }\n        });\n\n        let file = ProgressWriter::new(lock, &progress);\n        let mut archive = ArchiveWriter::new(file, &progress);\n        if let Some(diagnostics) = &diagnostics {\n            archive.add_diagnostics(diagnostics, &layout.worktree_root)?;\n        }\n        archive.add_repo(&repo, &layout, &output_path, repo_args.git_only)?;\n        let file = archive.finish(err)?;\n        let lock = file.into_inner();\n\n        let _ = counter\n            .join()\n            .map_err(|_| anyhow::anyhow!(\"Archive progress counter thread panicked\"))?;\n        persist_archive(lock)?;\n        Ok(())\n    })?;\n\n    writeln!(out, \"Archive at: {}\", output_path.path.display())?;\n    open_archive_dir_unless_requested(\n        &output_path.path,\n        repo_args.archive.no_open_archive_directory,\n    )?;\n    Ok(())\n}\n\n/// Return the effective current directory selected by `-C`.\nfn effective_current_dir(args: &Args) -> Result<PathBuf> {\n    Ok(std::env::current_dir()?.join(&args.current_dir))\n}\n\n/// Return the default archive path for `repo`, using `suffix` after the repository name.","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-debug/src/command/dump/mod.rs#L88-L124","documentation":"The `but debug dump` archive command spawns a thread that renders progress counters while the archive is written, then joins it before persisting the file. JoinHandle::join() returning Err means that progress-counter thread panicked mid-archive; the partially written archive is then not persisted and the whole dump is reported as failed.","triggerScenarios":"A panic inside the progress counter thread while ArchiveWriter streams the repository - e.g. progress state invalidated by an I/O error or a rendering/formatting bug in the counter thread.","commonSituations":"Terminal progress rendering hitting edge cases (unusual sizes, closed or piped stdout in CI); environments where the progress thread's assumptions about the terminal break.","solutions":["Re-run the dump command - transient rendering/IO conditions often clear on a second attempt","Capture stderr: the progress thread's own panic message is printed by the default panic hook and identifies the real bug","If reproducible, report it upstream with the stderr panic; as a workaround run the dump in a plain, non-interactive shell"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match run_dump(repo) {\n    Err(err) if err.to_string().contains(\"progress counter thread panicked\") => {\n        // retry once; on repeat, keep stderr (the thread's panic message) in the report\n    }\n    result => result,\n}","preventionTips":["Run `but debug dump` in a stable, non-interactive terminal when generating support archives","Always capture stderr alongside the command so thread panics are diagnosable","Keep dumps retryable: the command fails before persisting, so no partial archive is kept"],"tags":["debug","archive","thread-panic","progress"],"backgroundTag":"worker-thread-panic","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}