Awaiting a promise that I constructed exits code with no errors

I verified in the console that coordinator.setupPromise is a Promise, but when I run await coordinator.setupPromise , the code never gets to the print statement after the await and instead of waiting it just exits immediately. Example console output:

$ tsx main.ts 
setup 
await setup Promise { <pending> }

Heres my code:

import { ChildProcessWithoutNullStreams, spawn } from "child_process";
import { getPortFree, sleep } from "../utils";
import 'child_process'
import fetch, { RequestInit } from "node-fetch";
import { SocksProxyAgent } from "socks-proxy-agent";

class TorInstance {

    socksPort: number;
    controlPort: number;
    dataDir: string = `./datadirs/${Math.random().toString(36).slice(2)}`;

    torProcess: ChildProcessWithoutNullStreams;
    agent;
    setupRes;
    setupPromise = new Promise(res => { this.setupRes = res });

    constructor(socksPort?, controlPort?) {
        this.setup();
    }

    private async setup(socksPort?, controlPort?) {
        let port1 = await getPortFree();
        let port2 = await getPortFree();

        this.socksPort = socksPort ?? port1.port
        this.controlPort = controlPort ?? port2.port

        port1.server.close();
        port2.server.close();

        // tor --SocksPort 11111 --ControlPort 11112 --DataDirectory test1
        this.torProcess = spawn(`tor`, ['--SocksPort', this.socksPort, '--ControlPort', this.controlPort, '--DataDirectory', this.dataDir].map(String));
        this.torProcess.stdout.setEncoding('utf8');
        this.torProcess.stdout.on('data', (data) => {
            if (data.toString().includes(`[notice] Bootstrapped 100% (done): Done`)) { this.setupRes() }
        })
        this.agent = new SocksProxyAgent(`socks5h://127.0.0.1:${this.socksPort}`);
    }

    public fetch(url: string, options?: RequestInit) {
        return fetch(url, {
            ...options,
            agent: this.agent
        })
    }

    public dispose() {
        this.torProcess.kill();
    }


}

class TorCoordinator {
    instances: TorInstance[] = [];
    currentIndex = 0;
    setupRes;
    setupPromise = new Promise(res => { this.setupRes = res; })

    constructor(num: number) {
        this.createInstances(num);
    }

    fetch(url: string, options?: RequestInit) {
        return this.instances[this.currentIndex++].fetch(url, options);
    }

    createInstances(num) {
        let newInstances: TorInstance[] = [];
        for (let i = 0; i < num; i++) {
            let newInstance = new TorInstance();
            newInstances.push(newInstance);
            newInstance.setupPromise.then(() => {
                console.log('setup!!')
                this.instances.push(newInstance)
                this.setupRes();
            })
            // todo  monitor console output for [notice] Bootstrapped 100% (done): Done, and only add to main list then
        }
    }

}


async function test() {
    console.log('setup')
    let coordinator = new TorCoordinator(10);
    console.log('await setup',coordinator.setupPromise)

    await coordinator.setupPromise;
    console.log('done await')

    coordinator.fetch('https://api.ipify.org?format=json').then(res => res.text().then(console.log))
    coordinator.fetch('https://api.ipify.org?format=json').then(res => res.text().then(console.log))
    await sleep(10000)
}
test();

And utils.ts is:

import { SocksProxyAgent } from "socks-proxy-agent"

export function sleep(m) { return new Promise(r => setTimeout(r, m)) }
export const torAgent = new SocksProxyAgent('socks5h://127.0.0.1:9050');


import { Readable } from 'stream';

export async function streamToBuffer(stream) {
    const chunks = [];

    for await (const chunk of stream) {
        chunks.push(chunk); // Collect each Uint8Array chunk
    }

    // Concatenate all chunks into a single Buffer
    const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
    const buffer = Buffer.alloc(totalLength);
    let position = 0;

    for (const chunk of chunks) {
        buffer.set(chunk, position);
        position += chunk.length;
    }

    return buffer;
}


export async function streamToString(stream: ReadableStream) {
    const reader = stream.getReader()
    let html = ''
    while (true) {
        const { value, done } = await reader.read()
        if (value) {
            html += new TextDecoder().decode(value)
        }
        if (done) {
            return html
        }
    }
}

export async function streamToStringOld(stream: ReadableStream<Uint8Array<ArrayBufferLike>>) {
    const chunks: any = [];

    // Use async iteration to read from the stream
    for await (const chunk of stream) {
        chunks.push(chunk);  // Collect each Uint8Array chunk
    }

    // Concatenate all chunks into a single Uint8Array
    const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
    const resultArray = new Uint8Array(totalLength);

    let position = 0;
    for (const chunk of chunks) {
        resultArray.set(chunk, position);
        position += chunk.length;
    }

    // Convert the Uint8Array to a string
    return new TextDecoder().decode(resultArray);
}

import net from "net"

export async function getPortFree():Promise<{port:number,server:net.Server}> {
    return new Promise( res => {
        const srv = net.createServer();
        srv.listen(0, () => {
            // @ts-ignore
            const port = srv.address().port
            res({port,server:srv});
            
        });
    })
}

I tried awaiting a promise that I had constructed earlier, but instead of awaiting for passing to the next line, the code just exists with no error thrown.