Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: throw new Error('WebSocket is not open: readyState 0 (CONNECTING)'); #229

Open
2 tasks done
ghost opened this issue Oct 31, 2022 · 3 comments
Open
2 tasks done

Comments

@ghost
Copy link

ghost commented Oct 31, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

when i run node datav2.js
i got error
C:\Users\User\alpaca-trade-api-js\node_modules\ws\lib\websocket.js:394

      throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
      ^

Error: WebSocket is not open: readyState 0 (CONNECTING)
s:394:13)
    at AlpacaStocksClient.unsubscribe (C:\Users\User\alpaca-trade-api-js\node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\stock_websocket_v2.js:136:19)
modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\stock_websocket_v2.js:93:14)   
    at Timeout._onTimeout (C:\Users\User\alpaca-trade-api-js\datav2.js:63:14)
    at listOnTimeout (node:internal/timers:564:17)
    at process.processTimers (node:internal/timers:507:7)

Expected Behavior

can get data stream

SDK Version I encountered this issue in

2.16.1

Steps To Reproduce

npm install --save @alpacahq/alpaca-trade-api
https://github.com/alpacahq/alpaca-trade-api-js/blob/master/examples/websocket_example_datav2.js
node datav2.js

Filled out the Steps to Reproduce section?

  • I have entered valid steps to reproduce my issue or have attached a minimally reproducible case in code that shows my issue happening; and understand that without this my issue will be flagged as invalid and closed after 30 days.

Anything else?

No response

@majorsauce
Copy link

majorsauce commented Dec 8, 2022

Can you add a code snippet on how you connect the WebSocket and also when/how you subscribe to stuff ?
It´s not intended to simply run the JS file with Node, this is not actually a binary or standalone application but rather a library which should be used in context of code.
Also, the error indicates that you should only send subscriptions once the websocket is actually connected which can be determined by the "onConnect" function, eg:

function initAlpaca() {

	// Setup alpaca
	let alpaca = new Alpaca({
		keyId: 'PK...',
		secretKey: 'EQ...',
		paper: true,
	})

	// Get websocket for stock data
	const stockStream = alpaca.data_stream_v2;

	// Log errors
	stockStream.onError(e => console.log(e))

	// Run this function to execute stuff once connected, for instance subscribe to bars etc.
	stockStream.onConnect(() => {
		console.log("Alpaca connected!")
		stockStream.subscribeForBars(["TSLA"])
	})

	// Process streamed data
	stockStream.onStockBar(bar => console.log(bar))

	// Trigger the websocket to connect
	stockStream.connect()
	
}

@alexk984
Copy link

alexk984 commented Feb 9, 2023

Also have the same error which is crash my application every day. Error log:

10:14:07.773 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42      Alpaca Status: connecting
Error: WebSocket is not open: readyState 0 (CONNECTING)
    at WebSocket.ping (C:\www\fusion\node_modules\@alpacahq\alpaca-trade-api\node_modules\ws\lib\websocket.js:323:13)
    at AlpacaStocksClient.ping (C:\www\fusion\node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\websocket.js:159:19)
    at Timeout._onTimeout (C:\www\fusion\node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\websocket.js:128:18)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)
10:14:19.608 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42      Alpaca Status: authenticating
10:14:19.612 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42      Alpaca Status: connected
10:14:19.819 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42      Alpaca Status: authenticated
10:14:19.821 INFO \fusion\libs\alpaca\src\lib\AlpacaService.ts:113      Alpaca Subscribe quotes 
Exit...

My code:

   this.alpacaClient = new Alpaca({
      dataStreamUrl: 'wss://stream.data.alpaca.markets',
      keyId: process.env.NX_APCA_API_KEY_ID,
      secretKey: process.env.NX_APCA_API_SECRET_KEY,
      paper: true,
      feed: 'sip',
      apiVersion: 2,
    })

    const websocket = this.alpacaClient.data_stream_v2
    websocket.onStateChange((state) => {
      this._alpacaState = state
      alpacaLogger.debug('Status: ' + state)
      if (state === STATE.AUTHENTICATED) {
        this.subscribeQuotes()
        this.subscribeTrades()
      }
    })
    websocket.onError((err) => {
      alpacaLogger.debug('Error:' + err, 'hidden')
    })
    websocket.onConnect(() => {
      console.log('Alpaca connected!')
    })
    websocket.onStockQuote((quote) => {
      ....
    })
    websocket.onDisconnect(() => {
      alpacaLogger.debug('Disconnected...')
    })
    websocket.connect()

@RajRai
Copy link

RajRai commented Apr 2, 2023

I'm just messing around with the node_modules right now, it looks like changing this code (from "node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\websocket.js" in the following way resolves things. I say looks like because there are some other unchecked calls that I'm seeing, such as conn.ping(), so probably a similar change needs to be made wherever the error comes up.

Old:

    authenticate() {
        const authMsg = {
            action: "auth",
            key: this.session.apiKey,
            secret: this.session.secretKey,
        };
        this.conn.send(this.msgpack.encode(authMsg));
        this.emit(STATE.AUTHENTICATING);
        this.session.currentState = STATE.AUTHENTICATING;
    }

New:

    authenticate() {
        const authMsg = {
            action: "auth",
            key: this.session.apiKey,
            secret: this.session.secretKey,
        };
        if (this.conn.readyState == this.conn.OPEN){ // Check the socket state before calling send in case of a disconnect after the last 'open' emission
            this.conn.send(this.msgpack.encode(authMsg));
            this.emit(STATE.AUTHENTICATING);
            this.session.currentState = STATE.AUTHENTICATING;
        }
    }

It seems like, somehow, the socket has disconnected between emission of the OPEN state and the call to authenticate(). An authenticate() call is registered as a callback for the OPEN state when you call connect().

I think there's a better way of doing this which doesn't involve constantly checking the websocket state, and instead just properly handling the disconnect instead by cancelling any pending authorization or pings or whatever else. However, I know next to nothing about this project's internals, so this is the best I have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants