@@ -767,6 +767,9 @@ private Mono<DownloadOrResolveResult> buildRetryableDownload(InstallContext con
767767 return Mono .defer (() ->
768768 downloadOrResolveFile (context , modInfo , isWorld , outputSubdir , cfFile )
769769 .checkpoint ()
770+ .onErrorResume (throwable ->
771+ removeFailedDownload (throwable , outputSubdir , cfFile )
772+ )
770773 )
771774 // retry the deferred part above if one of the expected failure cases
772775 .retryWhen (
@@ -778,13 +781,32 @@ private Mono<DownloadOrResolveResult> buildRetryableDownload(InstallContext con
778781 throwable instanceof ChannelException
779782 )
780783 .doBeforeRetry (retrySignal ->
781- log .warn ("Retrying to download {} @ {}:{}" ,
782- cfFile .getFileName (), modInfo .getName (), cfFile .getDisplayName ()
784+ log .warn ("Retrying download of {} @ {}:{} due to {}" ,
785+ cfFile .getFileName (), modInfo .getName (), cfFile .getDisplayName (),
786+ retrySignal .failure ().getClass ().getSimpleName ()
783787 )
784788 )
785789 );
786790 }
787791
792+ private Mono <DownloadOrResolveResult > removeFailedDownload (
793+ Throwable throwable , Path outputSubdir , CurseForgeFile cfFile
794+ ) {
795+ final Path outputFile = resolveOutputFile (outputSubdir , cfFile );
796+ return Mono .<DownloadOrResolveResult >create (sink -> {
797+ try {
798+ log .trace ("Removing failed download of {}" , outputFile );
799+ if (Files .deleteIfExists (outputFile )) {
800+ log .debug ("Removed failed download of {}" , outputFile );
801+ }
802+ } catch (IOException e ) {
803+ log .error ("Unable to remove failed download of {}" , outputFile , e );
804+ }
805+ sink .error (throwable );
806+ })
807+ .subscribeOn (Schedulers .boundedElastic ());
808+ }
809+
788810 @ RequiredArgsConstructor
789811 static class DownloadOrResolveResult {
790812
@@ -799,7 +821,7 @@ static class DownloadOrResolveResult {
799821 private Mono <DownloadOrResolveResult > downloadOrResolveFile (InstallContext context , CurseForgeMod modInfo ,
800822 boolean isWorld , Path outputSubdir , CurseForgeFile cfFile
801823 ) {
802- final Path outputFile = outputSubdir . resolve ( cfFile . getFileName () );
824+ final Path outputFile = resolveOutputFile ( outputSubdir , cfFile );
803825
804826 // Will try to locate an existing file by alternate names that browser might create,
805827 // but only for non-world files of the modpack
@@ -829,6 +851,10 @@ private Mono<DownloadOrResolveResult> downloadOrResolveFile(InstallContext conte
829851 }
830852 }
831853
854+ private static @ NotNull Path resolveOutputFile (Path outputSubdir , CurseForgeFile cfFile ) {
855+ return outputSubdir .resolve (cfFile .getFileName ());
856+ }
857+
832858 /**
833859 * @return Mono.error with {@link FileHashInvalidException} when not valid
834860 */
0 commit comments