docs: private static void chunkedUploadFile(DbxClientV2 dbxClient, File localFile, String dropboxPath) {
          long size = localFile.length();
  
          // assert our file is at least the chunk upload size. We make this assumption in the code
          // below to simplify the logic.
          if (size < CHUNKED_UPLOAD_CHUNK_SIZE) {
              System.err.println("File too small, use upload() instead.");
              System.exit(1);
              return;
          }
  
          long uploaded = 0L;
          DbxException thrown = null;
  
          ProgressListener progressListener = new ProgressListener() {
              long uploadedBytes = 0;
              @Override
              public void onProgress(long l) {
                  printProgress(l + uploadedBytes, size);
                  if (l == CHUNKED_UPLOAD_CHUNK_SIZE) uploadedBytes += CHUNKED_UPLOAD_CHUNK_SIZE;
              }
          };
  
          // Chunked uploads have 3 phases, each of which can accept uploaded bytes:
          //
          //    (1)  Start: initiate the upload and get an upload session ID
          //    (2) Append: upload chunks of the file to append to our session
          //    (3) Finish: commit the upload and close the session
          //
          // We track how many bytes we uploaded to determine which phase we should be in.
          String sessionId = null;
          for (int i = 0; i < CHUNKED_UPLOAD_MAX_ATTEMPTS; ++i) {
              if (i > 0) {
                  System.out.printf("Retrying chunked upload (%d / %d attempts)\n", i + 1, CHUNKED_UPLOAD_MAX_ATTEMPTS);
              }
  
              try (InputStream in = new FileInputStream(localFile)) {
                  // if this is a retry, make sure seek to the correct offset
                  in.skip(uploaded);
  
                  // (1) Start
                  if (sessionId == null) {
                      sessionId = dbxClient.files().uploadSessionStart()
                          .uploadAndFinish(in, CHUNKED_UPLOAD_CHUNK_SIZE, progressListener)
                          .getSessionId();
                      uploaded += CHUNKED_UPLOAD_CHUNK_SIZE;
                      printProgress(uploaded, size);
                  }
  
                  UploadSessionCursor cursor = new UploadSessionCursor(sessionId, uploaded);
  
                  // (2) Append
                  while ((size - uploaded) > CHUNKED_UPLOAD_CHUNK_SIZE) {
                      dbxClient.files().uploadSessionAppendV2(cursor)
                          .uploadAndFinish(in, CHUNKED_UPLOAD_CHUNK_SIZE, progressListener);
                      uploaded += CHUNKED_UPLOAD_CHUNK_SIZE;
                      printProgress(uploaded, size);
                      cursor = new UploadSessionCursor(sessionId, uploaded);
                  }
  
                  // (3) Finish
                  long remaining = size - uploaded;
                  CommitInfo commitInfo = CommitInfo.newBuilder(dropboxPath)
                      .withMode(WriteMode.ADD)
                      .withClientModified(new Date(localFile.lastModified()))
                      .build();
                  FileMetadata metadata = dbxClient.files().uploadSessionFinish(cursor, commitInfo)
                      .uploadAndFinish(in, remaining, progressListener);
  
                  System.out.println(metadata.toStringMultiline());
                  return;
              } catch (RetryException ex) {
                  thrown = ex;
                  // RetryExceptions are never automatically retried by the client for uploads. Must
                  // catch this exception even if DbxRequestConfig.getMaxRetries() > 0.
                  sleepQuietly(ex.getBackoffMillis());
                  continue;
              } catch (NetworkIOException ex) {
                  thrown = ex;
                  // network issue with Dropbox (maybe a timeout?) try again
                  continue;
              } catch (UploadSessionLookupErrorException ex) {
                  if (ex.errorValue.isIncorrectOffset()) {
                      thrown = ex;
                      // server offset into the stream doesn't match our offset (uploaded). Seek to
                      // the expected offset according to the server and try again.
                      uploaded = ex.errorValue
                          .getIncorrectOffsetValue()
                          .getCorrectOffset();
                      continue;
                  } else {
                      // Some other error occurred, give up.
                      System.err.println("Error uploading to Dropbox: " + ex.getMessage());
                      System.exit(1);
                      return;
                  }
              } catch (UploadSessionFinishErrorException ex) {
                  if (ex.errorValue.isLookupFailed() && ex.errorValue.getLookupFailedValue().isIncorrectOffset()) {
                      thrown = ex;
                      // server offset into the stream doesn't match our offset (uploaded). Seek to
                      // the expected offset according to the server and try again.
                      uploaded = ex.errorValue
                          .getLookupFailedValue()
                          .getIncorrectOffsetValue()
                          .getCorrectOffset();
                      continue;
                  } else {
                      // some other error occurred, give up.
                      System.err.println("Error uploading to Dropbox: " + ex.getMessage());
                      System.exit(1);
                      return;
                  }
              } catch (DbxException ex) {
                  System.err.println("Error uploading to Dropbox: " + ex.getMessage());
                  System.exit(1);
                  return;
              } catch (IOException ex) {
                  System.err.println("Error reading from file \"" + localFile + "\": " + ex.getMessage());
                  System.exit(1);
                  return;
              }
          }
  
          // if we made it here, then we must have run out of attempts
          System.err.println("Maxed out upload attempts to Dropbox. Most recent error: " + thrown.getMessage());
          System.exit(1);
      }