Bot Framework V4 - TypeError: Cannot perform 'get' on a proxy that has been revoked

Viewed 15156

I am trying to make a rest query against a database that stores knowledge articles for users and returns an array of results based on what the user has searched for. Whenever I try to search I get:

"TypeError: Cannot perform 'get' on a proxy that has been revoked"

I have tried adding it to async as shown but I still keep getting the same error. Any idea what I am doing wrong?

const Response = async (turnContext) => {
    if (turnContext.activity.value.choice === 'feedbackProvider') {
        try {
            const feedbackBody = turnContext.activity.value.feedbackBody;
            const feedbackEmail = turnContext.activity.value.feedbackEmail;
            storage.write(feedbackBody, feedbackEmail);
            await turnContext.sendActivity(`Feedback Sent`);
        } catch (err) {
            console.log('fetch failed', err);
        }
    } else if (turnContext.activity.value.choice === 'issueRaiser') {
        try {
            const bugTitle = turnContext.activity.value.issueTitle;
            const bugDesc = turnContext.activity.value.issueDescription;
            const bugEmail = turnContext.activity.value.issueEmail;
            const request = require('request');
            request({
                method: 'Post',
                uri: `<uri>issues?title=${ bugTitle }&description=${ bugDesc } ${ bugEmail }&labels=bug`,
                json: true,
                headers: {
                    'Private-Token': '<token>'
                }
            });
            turnContext.sendActivity(`Issue Raised`);
        } catch (err) {
            console.log('fetch failed', err);
        }
    } else if (turnContext.activity.value.choice === 'knowledgeBaseSearch') {
        try {
            const knowledgeBaseTopic = turnContext.activity.value.knowledgeBaseTopic;
            request({
                url: process.env.SN_KB_URL + knowledgeBaseTopic,
                json: true,
                auth: {
                    'username': process.env.Ticket_User,
                    'password': process.env.Ticket_Key
                }
            }, async (error, response, body) => {
                try {
                    var stuff = [];
                    for (var i = 0, len = body.result.length; i < len; i++) {
                        stuff.push(
                            CardFactory.heroCard(body.result[i].short_description, ['imageUrl1'], [`${ process.env.SN_KB_Resp_URl }${ body.result[i].number }`])

                        );
                    }
                    let messageWithCarouselOfCards = MessageFactory.carousel(stuff);
                    await turnContext.sendActivity(messageWithCarouselOfCards);
                } catch (err) {
                    console.log(error);
                }
            });
        } catch (err) {
            console.log('fetch failed', err);
        }
    }
};

Full Error Message:

TypeError: Cannot perform 'get' on a proxy that has been revoked
cardMiddleware.js:35
    at Request.request [as _callback] (c:\Bots\sdk4-2\skills\cardMiddleware.js:35:45)
    at Request.self.callback (c:\Bots\sdk4-2\node_modules\request\request.js:186:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)
    at Request.<anonymous> (c:\Bots\sdk4-2\node_modules\request\request.js:1163:10)
    at emitOne (events.js:116:13)
    at Request.emit (events.js:211:7)
    at IncomingMessage.<anonymous> (c:\Bots\sdk4-2\node_modules\request\request.js:1085:12)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:111:20)

From my post on the forum I was informed that I was using a request module that did not support Promises, which I believe was causing my error. I've now began to use Axios for my request which is shown below;

try {
    return await axios.get(process.env.SN_KB_URL + knowledgeBaseTopic, {
        headers: {
          auth: {
          username: process.env.Ticket_User,
          password: process.env.Ticket_Key
        }
      }
    })
  }

However now when I run the request I get a 401 'Unauthorised' error and I'm not sure what is wrong with my request.

6 Answers

The answer for me was to double check I didn't miss any await usage that might be necessary. Turns out I called this.dialog.run(context, this.dialogState); without the await and that threw the same error. I found the answer on this Github issue

This issue happened because I was using a request module that did not support promises. Changing my request module for one that did support promises (which I found out about by using this article) resolved the issue.

I spent a lot of time struggling with this issue. As other commenters have noted, the issue lies in the fact that the Lex Runtime is not promise-based, so you cannot await requests, which causes the proxy to be revoked.

Here is my solution:

async callLex(context) {
    const params = {
        botAlias: 'prod',
        botName: 'botName',
        userId: context.activity.from.id,
        contentType: 'text/plain; charset=utf-8',
        accept: 'text/plain; charset=utf-8',
        inputStream: context.activity.text.trim()
    }
    let request = lexruntime.postContent(params)
    await request.promise().then(
        async response => {
            console.log(response)
            console.log('Success!')
            await context.sendActivity(response.message)          
        },
        err => {
            console.log(err)
            console.log('Error!')
        })
}

Rather than directly invoke the request like "lexruntime.postContent(params, callback func)", I exclude the callback function and utilize the "promise" property of AWS.Request to send the request as a promise which enables me to use "await" and keeps the proxy open. See documentation here.

I'm going to put this here only because it's the first result that pops up when searching, although it doesn't directly relate to this issue.

There's a very easy way to use setTimeout() and avoid this error:

await new Promise(resolve => setTimeout(() => resolve(
    turnContext.sendActivity('I was sent 5 seconds later')
), 5000));

In my scenario, we were trying to upload files from a Task Module (modal popup of teams) to the bot and in response the bot would give a first confirmation that the attachments are uploading. This activity would close the task module (as the bot must reply within 10 seconds or teams would resend the request). Now when the attachments were uploaded, we wanted to update the previously sent adaptive card with the list of the uploaded attachments. We achieved this using the proactive messaging feature of bot framework.

const conversationReference = TurnContext.getConversationReference(activity);
Promise.all(listOfPromises).then(() => {
    await botAdapter.continueConversation(conversationReference, async turnContext => {
        await turnContext.sendActivity('All attachments uploaded!');
    });
}

Docs: https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-proactive-message?view=azure-bot-service-4.0&tabs=javascript

Check for lines that needs await inside any aync function. I hope that azure will point usto which file or line specifically but I have not figured it out until I looked at all my functions.

Okay, so this is indeed a very cryptic error message as the github thread here suggested .

But I found that I was not await ing in this block:

    this.onMessage(async (context, next) => {.
      const didBotWelcomedUser = await this.welcomedUserProperty.get(
        context,
        "false"
      );  

      if (didBotWelcomedUser === false) {
        // first time user is in chat
        await this.sendWelcomeMessage(context); `<-------- await here was missing`
      } else {
        await this.sendSuggestedAction(context); `<-------- await here was missing`
      }



      await next();
    });

    this.onMembersAdded(async (context, next) => {


      await this.sendWelcomeMessage(context);
      await next();
    });
  }

I thought await.next() is enough. We all gotta learn this somehow... Hope you resolve yours.

Related