function try_download_using_fetch() {
    local output=$1
    local url=$2
    local platform=$PLATFORM
    local arch=$ARCH
    if [ -z "$SERVER_DIR" ] || [ -z "$SERVER_DOWNLOAD_PREFIX" ]; then
        return 1
    fi

    if [[ "$arch" == "x86_64" ]]; then
        arch="x64"
    elif [[ "$arch" == "aarch64" ]]; then
        arch="arm64"
    fi

    local fetchUrl="${SERVER_DOWNLOAD_PREFIX}fetch-$platform-$arch.tar.gz"
    cd $SERVER_DIR

    local PREV_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
    export LD_LIBRARY_PATH="$SERVER_DIR/fetch"

    # Download and extract fetch tool if not already present
    if ! ./fetch/fetch --version >/dev/null 2>&1; then
        local tmpfile="$SERVER_DIR/fetch_tmp.tar.gz"
        rm -f "$tmpfile"
        echo "download fetch: $fetchUrl"
        if [ -n "$(which curl)" ]; then
            curl --connect-timeout 10 -sSfL "$fetchUrl" -o "$tmpfile" 2>&1
        elif [ -n "$(which wget)" ]; then
            wget --timeout=10 -qO "$tmpfile" "$fetchUrl" 2>&1
        else
            export LD_LIBRARY_PATH="$PREV_LD_LIBRARY_PATH"
            return 1
        fi
        # Verify download succeeded and archive is valid
        if [ $? -ne 0 ] || [ ! -s "$tmpfile" ] || ! tar tzf "$tmpfile" >/dev/null 2>&1; then
            echo "fetch tool download failed or corrupted, falling back to curl/wget"
            rm -f "$tmpfile"
            export LD_LIBRARY_PATH="$PREV_LD_LIBRARY_PATH"
            return 1
        fi
        tar zxf "$tmpfile"
        rm -f "$tmpfile"
    fi

    code=1
    if ./fetch/fetch --version >/dev/null 2>&1; then
        # Use SERVER_DIR for fetch chunk temp files instead of system temp dirs.
        # XDG_RUNTIME_DIR (/run/user/xxx) is a tmpfs that may be cleaned up by
        # systemd-tmpfiles-clean during long downloads, causing "No such file or directory"
        # errors for later chunks. Keeping chunks under SERVER_DIR ensures they live on the
        # same filesystem as the final output and avoids tmpfs cleanup issues.
        # TMPDIR must be set (not TMP_DIR) since Rust's std::env::temp_dir() reads TMPDIR.
        local fetch_tmpdir="$SERVER_DIR/.fetch-tmp"
        mkdir -p "$fetch_tmpdir"
        TMPDIR="$fetch_tmpdir" ./fetch/fetch download -c 20 --no-resume -r 1 --chunk-retries 3 --chunk-size 2M --config-file "$SERVER_DIR/../fetch.config.json" "$url" -o "$output"
        code=$?
        rm -rf "$fetch_tmpdir"
    fi
    echo "fetch download code: $code"
    export LD_LIBRARY_PATH="$PREV_LD_LIBRARY_PATH"
    return $code
}
