Botframework-sdk: Stack is empty

Created on 9 Mar 2017  路  10Comments  路  Source: microsoft/botframework-sdk

I've updated our beta version of Azure Bot to a more recent version of the Bot Builder .NET SDK (3.5.2). It is now working fine with the emulator and on Slack (my test is list vms, list subscriptions, list runbooks and all three work well on those two channels).

But for some reason on Skype when I try the same commands, the 'list runbooks' one fails and the bot responds with "Sorry, my bot code is having an issue."

I enabled error logging on the Azure Web App for it. The last conversation id with the failure is 29:1iVz4E7ch7dwQaneg4JJ4JtLzOw33MtYW3KsoPJgLBgc if you can help investigate, and below is the exception from the log. Any ideas what is happening and why only on Skype?

Buffer="{
"message": "An error has occurred.",
"exceptionMessage": "Stack is empty",
"exceptionType": "System.InvalidOperationException",
"stackTrace": " at Microsoft.Bot.Builder.Internals.Fibers.Extensions.PeekT\r\n at Microsoft.Bot.Builder.Internals.Fibers.Fiber1.<Microsoft-Bot-Builder-Internals-Fibers-IFiberLoop<C>-PollAsync>d__16.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.DialogTask.<Microsoft-Bot-Builder-Base-IEventLoop-PollAsync>d__23.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.ReactiveDialogTask.<Microsoft-Bot-Builder-Base-IEventLoop-PollAsync>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.ScoringEventLoop1.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.PersistentDialogTask.d__4.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at Microsoft.Bot.Builder.Dialogs.Internals.PersistentDialogTask.d__4.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.ExceptionTranslationDialogTask.d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.SerializeByConversation.d__4.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.SetAmbientThreadCulture.d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.PostUnhandledExceptionToUser.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at Microsoft.Bot.Builder.Dialogs.Internals.PostUnhandledExceptionToUser.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Internals.LogPostToBot.d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Conversation.d__4.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Microsoft.Bot.Builder.Dialogs.Conversation.d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at AzureBot.MessagesController.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Threading.Tasks.TaskHelpersExtensions.d__3`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Web.Http.Filters.ActionFilterAttribute.d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Filters.ActionFilterAttribute.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()"
}"

Most helpful comment

Not sure if this is related to the original problem but I am getting the "Stack is Empty" exception on this code when I call the dialog using context.Forward from another dialog:

    public async Task StartAsync(IDialogContext context)
    {
        context.Wait(UserProfileStep1);
    }

    public async Task UserProfileStep1(IDialogContext context, IAwaitable<object> original)
    {
        string originalMessage = (string)await original; // <== the exception occurs here

The reason of that was that I tried to pass a string using context.Forward, while it seems to only support IMessageActivity.

All 10 comments

FYI it is also working fine on our test console app

I could see that happening if you have

  1. an unbalanced number of pushes and pops
  2. you don't have a IDialog.Loop at the root of your dialog stack

As for why you only see it with Skype, perhaps there is an exception thrown only for that channel?

Hmm, ok thanks. I wonder if the stack got messed up between my user and the Skype channel. How would I reset the stack and context and basically start from scratch with the Skype channel? "/deleteprofile" doesn't seem to work. (sample code would be appreciated it I need to add it as a command to the bot).

Ok, from @msft-shahins mentions in other issues I repeated what DeleteProfileScorable does and reset the stack: https://github.com/Microsoft/AzureBot/blob/beta/AzureBot/Dialogs/RootDialog.cs#L47-L53

But even after that, resetting everything and starting over, the Skype channel still throws the exception I raised above when I run 'list runbooks'.

Any chance you can investigate the actual conversation and shed some light? Here's the latest conversation id from AzureBotBeta:
"conversation":{"id":"29:1iVz4E7ch7dwQaneg4JJ4JtLzOw33MtYW3KsoPJgLBgc"}

Check if you have a missing wait operator in your code:

http://stackoverflow.com/questions/42694361/stack-is-empty-in-microsoft-bot-framework

@nzthiago that method to reset the dialog stack is intended for use outside of the dialog system. When you call IDialogStack.Reset like that, you're still executing in RootDialog which thought it was on the stack. If you want to escape out of a dialog stack, you can throw an exception which will propagate up the dialog stack and and allow cleanup, and then you can catch that exception at the top of the stack to prevent the user from seeing it.

By the way, if that's your root dialog, what other dialogs are on the stack anyway?

Oh I see, I can't call that from inside a dialog...
I have other dialogs in the solution, that the root one calls, like this one:
https://github.com/Microsoft/AzureBot/blob/beta/AzureBot.Services.Runbooks/Dialogs/AutomationDialog.cs

I enabled remote debugging on the web app hosting the beta version of the bot, and looked at the context object and it shows three things in the stack when I go into fiber stack for it with three items in the stack:

screen shot 2017-03-30 at 2 36 13 pm

Below is the stack trace I got on the client side, with a message "Unknown", so I'm still at a loss on why this only happens for Skype and what the error is, it's right at a "context.PostAsync" call as per the printscreen above...

Microsoft.Rest.HttpOperationException occurred
HResult=-2146233088
Message=Unknown
Source=Microsoft.Bot.Connector
StackTrace:
at Microsoft.Bot.Connector.ErrorHandling.d__2`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Connector.ConversationsExtensions.d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Builder.Dialogs.Internals.AlwaysSendDirect_BotToUser.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Builder.Dialogs.Internals.MapToChannelData_BotToUser.d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Builder.Dialogs.Internals.LogBotToUser.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Builder.Dialogs.Internals.DialogContext.d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Bot.Builder.Dialogs.Extensions.d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at AzureBot.Dialogs.AutomationDialog.d__2.MoveNext() in C:\a\1\s\AzureBot.Services.Runbooks\Dialogs\AutomationDialog.cs:line 75
InnerException:

I moved the code to reset the stack into the controller and outside the root dialog:
https://github.com/Microsoft/AzureBot/blob/beta/AzureBot/Controllers/MessagesController.cs#L29-L36

This properly resets the stack and the bot starts all over again with an empty stack. But if I run through the same flow (login, list vms, list runbooks) it still fails with the same error messages in Skype as above ("Stack is empty' on the server side) after the 'list runbooks' command. So I'm still not sure why Skype is failing there.
I even looked for missing wait operators in the code as recommended above but couldn't find any.

Anything else I should try? Can we get someone working in the Skype channel to help perhaps?

Not sure if this is related to the original problem but I am getting the "Stack is Empty" exception on this code when I call the dialog using context.Forward from another dialog:

    public async Task StartAsync(IDialogContext context)
    {
        context.Wait(UserProfileStep1);
    }

    public async Task UserProfileStep1(IDialogContext context, IAwaitable<object> original)
    {
        string originalMessage = (string)await original; // <== the exception occurs here

The reason of that was that I tried to pass a string using context.Forward, while it seems to only support IMessageActivity.

Was this page helpful?
0 / 5 - 0 ratings