How to debug MissingLedgerHistoryError using Nodejs

Hi there everyone, I hope all is well with you.

I’m using Nodejs v14.16.0 and cannot figure out why I’m getting a MissingLedgerHistoryError for the following api.getTransactions() method.

I’m using: wss://s.altnet.rippletest.net:51233

router.post('/api/getTransactions', async (req, res) => {
    api.on('error', (errorCode, errorMessage) => {
      console.log(errorCode + ': ' + errorMessage)
    })
    api.on('connected', () => {
      console.log('connected')
    })
    api.on('disconnected', (code) => { // will be 1000 if this was normal closure
      console.log('disconnected, code:', code)
    })
    api.connect()
    .then( async () => {
      /* begin custom code ------------------------------------ */
      console.log('getting account info for', address)
      await api.getTransactions(address)
    })
    .then(info => {
      console.log("info",info);
      console.log('getTransactions done')
      res.send(info)
      /* end custom code -------------------------------------- */
    })
    .then(() => {
      return api.disconnect()
    })
    .catch(console.error)
})

Error returned is:
MissingLedgerHistoryError: Server is missing ledger history in the specified range
at /home/paul/sites/xrp2/backend/node_modules/ripple-lib/dist/npm/ledger/transactions.js:123:19
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async /home/paul/sites/xrp2/backend/routers/xrp.js:315:7 {
data: undefined
}

Perhaps someone may be able to suggest a solution to this for me?

Many thanks.

Paul

It is possible the testnet server s.altnet.rippletest.net does not have full ledger history. Perhaps you may want to pass an optional parameter:

{
    "minLedgerVersion": 42000000,
    "earliestFirst": true,
    "types": ["payment"]
  }

and narrow down what you’re looking for?

I believe there’s an error with the code you posted:

    api.connect()
    .then( async () => {
      /* begin custom code ------------------------------------ */
      console.log('getting account info for', address)
      await api.getTransactions(address)
    })
    .then(info => {
      console.log("info",info);
      console.log('getTransactions done')
      res.send(info)
      /* end custom code -------------------------------------- */
    })

After you connect, you call ‘await api.getTransactions(address)’ which should retrieve data, but that data isn’t being returned by the function.
In the next section, the variable ‘info’ will always be ‘void’ since nothing is returned from the previous function.

This might not be related to the ‘MissingLedgerHistoryError’ but still needs to be addressed.

Here’s a fix for that problem:

    api.connect()
    .then( async () => {
      console.log('getting account info for', address)
      // When you're returning from an async function, you don't need to use 'await' on the return 
      // but it's not harmful either.
      return api.getTransactions(address) 
    })
    .then(info => {
      console.log("info",info);
      console.log('getTransactions done')
      res.send(info)
    })

Regards.

EDIT

On an aside, it’s still a good idea to have a good understanding of JS promises and async functions in general but I often find the async-await form to be more legible when chaining async functions.
The following is equivalent to the code you posted but uses the async-await form instead:

	router.post('/api/getTransactions', async (_request, response) =>
	{
		//	Converted these three event handlers to use 'FatArrow' notation. It's functionally equivalant in this context but slightly more expressive.
		api.on('error', (errorCode, errorMessage) => console.log(errorCode + ': ' + errorMessage));
		api.on('connected', () => console.log('connected'));
		api.on('disconnected', (code) => console.log('disconnected, code:', code));

		//	Await the connection, api.connect() returns void.
		await api.connect();

		console.log('getting account info for', address);

		//	api.getTransactions(address) returns Promise<GetTransactionsResponse> 
		//	so when we 'await' the function, the promise is stripped off and we're left with the 'GetTransactionsResponse' object
		//	which we initialize 'transactions' to.
		const transactions = await api.getTransactions(address);

		console.log("info", transactions);
		console.log('getTransactions done');

		await response.send(transactions);
		await api.disconnect();
	}).catch(console.error);	//	We still use the promise form for error handling here.

One more helpful bit: When posting code on this forum (and many other online apps/services) wrap your code with three backtick characters.

Type three backticks (```) on it’s own line,
hit enter,
paste code,
then add an additional three backticks on it’s own line after.

Cheers.

2 posts were split to a new topic: Missing Destination Tag

How do join the XRP smart contract