I'm specifically asking what the issues may be with my try/catch block, which isn't described in the issues linked as "duplicates" to this.
I'm having an issue where I'm trying to catch a StaleElementReferenceException and then look up the element again but for some reason the exception isn't being caught. I have the method below and when I run the test I get a StaleElementReferenceException when this line is executed, value = element.GetAttribute(attributeName);. I assumed (maybe poorly) that adding the check in a try/catch and specifically looking for the exception would allow me to continue trying until selenium is able to find the element again. The issue is for some reason the exception isn't getting caught and the test immediately exits. Oddly, if I change the catch block to just catch the general Exception it works just fine. My concern with that is though I could get in a loop that would never exit. I'm using a page object model to initially initialize the elements.
bool isStale = false;
string value = "";
do
{
try
{
value = element.GetAttribute(attributeName);
isStale = false;
}
catch (StaleElementReferenceException)
{
element = driver.FindElement(By.XPath(xPath));
isStale = true;
}
} while (isStale == true);
return value;
This is part of the stack trace:
Test failed with error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> OpenQA.Selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document (Session info: chrome=71.0.3578.98) (Driver info: chromedriver=2.43.600210 (68dcf5eebde37173d4027fa8635e332711d2874a),platform=Windows NT 10.0.17134 x86_64) at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse) at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary2 parameters) at OpenQA.Selenium.Remote.RemoteWebElement.Execute(String commandToExecute, Dictionary2 parameters) at OpenQA.Selenium.Remote.RemoteWebElement.GetAttribute(String attributeName)
Related
I already have Toast Notifications working, but I need to create a collection for them.
Following the code example in : https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/toast-collections
I get a crash on the GetToastCollectionManager call.
System.Exception
HResult=0x80070490
Message=Element not found. (0x80070490)
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
This exception was originally thrown at this call stack:
WpfApp1.MainWindow.CreateToastCollection() in MainWindow.xaml.cs
I'm not sure if I'm missing something obvious , but I cannot find examples or tutorials on Toast Notifications.
Any Ideas ?
public async void CreateToastCollection()
{
ToastNotificationManagerForUser defaultManager = ToastNotificationManager.GetDefault();
ToastCollectionManager collectionManager = defaultManager.GetToastCollectionManager();
string displayName = "Is Potato";
string launchArg = "NavigateToPotato";
System.Uri iconURI = new System.Uri("ms-appx:///Assets/icon.png");
ToastCollection licensingManagerToastCollection = new ToastCollection(
"MyToastCollection",
displayName,
launchArg,
iconURI);
// Calls the platform to create the collection
await collectionManager.SaveToastCollectionAsync(licensingManagerToastCollection);
}
The following is some code that downloads a file using System.Net.Http.HttpClient
try
{
var responseResult = new System.Net.Http.HttpClient().GetAsync(fileUrl);
using (var memStream = responseResult.Result.Content.ReadAsStreamAsync().Result)
{
using (var fileStream = File.Create(saveToPath))
{
memStream.CopyTo(fileStream);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
Sometimes I call this and a file fails to download. In that situation, the catch is called but doesn't contain any information of the issue:
One or more errors occurred.
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at SpPrefetchIndexBuilder.FileDownloader.StartDownloads(Int32 timeout)
How can I get it to the cause of this exception?
Task.Result throws AggregateException, so you can catch that. All exceptions will be inside InnerExceptions property of that exception (there can be multiple in theory, but in your case there will be just one). First of those exceptions (or the only one if there is just one) is also in InnerException property.
If you don't want to dig inside AggregateException, use .GetAwaiter().GetResult() instead of .Result - this will not wrap exception into AggregateException and will throw it as is.
Since you're calling .Result on the task, original exception will be held in InnerException property of catched exception. You could access it with following construct:
string message = e?.InnerException.Message ?? e.Message;
Not really sure if this applies but have you tried?: Console.WriteLine(ex.GetBaseException().ToString().StackTrace)
I have code that catches all exceptions that are thrown by a server call as follows:
new public Task SaveAsync()
{
return ServerException.Wrap(base.SaveAsync);
}
Where ServerException.Wrap looks like:
public static async Task<T> Wrap<T>(Func<Task<T>> func)
{
try
{
return await func();
}
catch (Exception ex)
{
// This is an internal error that shouldn't happen.
throw new ServerException(ex);
}
}
public static async Task Wrap(Func<Task> func)
{
await Wrap(async () =>
{
await func();
return true;
});
}
And then I have a function that calls SaveAsync as follows:
try
{
await problem.SaveAsync();
}
catch (ServerException ex)
{
Logger.LogException("Error saving problem.", ex);
}
I have some internal error that generates an exception which I catch in the above line and then it gets logged as follows:
2015-10-20 11:20:44.502 [Line 99] Error saving problem. (Exception:
Exceptions.ServerException: ---> System.ArgumentException: An item
with the same key has already been added. at
System.ThrowHelper.ThrowArgumentException (ExceptionResource resource)
[0x00000] in
/Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:74
However a few seconds later I get an unhanded exception warning that gets logged:
2015-10-20 11:21:16.352 Warning: Unhandled exception:
System.AggregateException: A Task's exception(s) were not observed
either by Waiting on the Task or accessing its Exception property. As
a result, the unobserved exception was rethrown by the finalizer
thread. ---> System.ArgumentException: An item with the same key has
already been added. at System.ThrowHelper.ThrowArgumentException
(ExceptionResource resource) [0x00000] in
/Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:74
Why do I get the second unobserved exception, even though I am catching and handling the first exception? This exception seems to be thrown by my ServerException.Wrap method.
I am using MonoTouch.
You need to explicitly set the exception to observed.
For that, you need to subscribe to the TaskScheduler's UnobservedTaskException event, and set it explicitly to observed (call SetObserved() on it).
See here:
UnobservedTaskException being throw...
EDIT:
Of course, you can also just catch AggregateException as well, or use ContinueWith() to observe and resume the task.
See the bottom of the official documentation:
Exception Handling (MSDN)
I have been playing around with Exceptions to learn more about how I should use them properly. So far, I know that throw keeps the original stack trace; throw new CustomException(...) is generally used when wanting to add more information about the exception that took place or add/change the message, or even change the type of Exception itself; and throw ex should never ever be used, unless I want to lose the original stack trace.
So I wrote a small program where I could catch and rethrow an exception several times while adding something to the original message.
public class Sample
{
static void Main(string[] args)
{
new Tester().FirstCall();
}
}
public class Tester
{
public void FirstCall()
{
try
{
SecondCall();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.Message);
}
}
public void SecondCall()
{
try
{
ThirdCall();
}
catch (GoodException ex)
{
throw new Exception(ex.Message, ex);
}
}
public void ThirdCall()
{
try
{
FourthCall();
}
catch (ArithmeticException ae)
{
throw new GoodException("Arithmetic mistake: " + ae.Message, ae);
}
}
public void FourthCall()
{
int d = 0;
int x = 10 / d;
}
}
Where GoodException is a custom exception implemented correctly.
I'm expecting the console to display something like this:
at PlayingWithExceptions.Tester.FourthCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 67
at PlayingWithExceptions.Tester.ThirdCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 59
at PlayingWithExceptions.Tester.SecondCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 41
at PlayingWithExceptions.Tester.FirstCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 25
Arithmetic mistake: Attempted to divide by zero.
But instead I'm getting this:
at PlayingWithExceptions.Tester.SecondCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 41
at PlayingWithExceptions.Tester.FirstCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 25
Arithmetic mistake: Attempted to divide by zero.
For some reason it only goes as far as the second call. Even though I'm passing the caught exception as an InnerException, the stack trace is still lost. I'm aware that if I just wrote throw instead of throwing a new exception, I could keep the original stack trace, but if I do that I won't be able to change the original message (which was the whole point of this exercise).
So my question is, what can I do to change the Exception message AND keep the original stack trace the whole way?
EDIT: Since an exception should not be used logic control and only caught once, the proper way to keep the original stack trace AND show the new message is to wrap the FourthCall in a try/catch (where the new Exception with its message is generated), and catch it only once all the way up in the FirstCall.
The stack trace isn't "lost" it's pushed into the InnerException, just like you told it to be. The "outer" exception in this case, did not participate in the call chain of the Inner exception - it's a brand new exception which originates in SecondCall, so that's the beginning of its stack trace.
And yes, the commenters are correct. To control your messaging, you won't do that by trying to set the message in the Exception object - Exceptions should be handled by code, messages are for users. So, you'll log the message, display it to the user, something like that.
Don't know if it still relevant for you. Just use the keyword "throw" without the exception append to it , then the trace will not be lost and the original exception will be throws. not as inner.
Below is some logging output from a .NET application.
Error in MainFunction.
Message: Exception of type 'System.OutOfMemoryException' was thrown.
InnerException:
StackTrace: at System.Text.StringBuilder.ToString()
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Exception.GetStackTrace(Boolean needFileInfo)
at System.Exception.ToString(Boolean needFileLineInfo)
at System.Exception.ToString()
[the rest of the trace is removed]
Which corresponds to the following line of application code. The following is in a catch block, and returns the string to the method that actually throws:
private void MainFunction()
{
...
try
{
string doc = CreateXMLDocument(); // <- Out of Memory throws here
}
catch (Exception ex)
{
CoreLogging("Error in MainFunction.", ex);
}
}
private string CreateXMLDocument()
{
try
{
//Some basic and well constrained XML document creation:
...
}
catch (Exception ex)
{
return "Exception message: " + ex.ToString(); // <- This is the last line of the trace
}
}
What should I make of this? Clearly Exception.Message should be used instead of Exception.ToString(), but I'd still like to understand this. Does
at System.Text.StringBuilder.ToString()
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
mean that the stack trace of the exception in CreateXMLDocument was so mammoth caused OutOfMemory? I'm curious to see how that would occur as there's definitely no circular calls in CreateXMLDocument, which is the only thing I can think of that could cause an enormous stack trace.
Has anyone else encountered a similar situation?
I little bit of guessing:
1) CLR rises a OutOfMemoryException. 2) You catch this exception and call .ToString on it
3) ToString() tries to allocate memory to the stack trace but... there is no memory and another OutOfMemoryException is rised.
In the comments you said that the XML documents have a few hundreds of kbytes, this could be a/the problem if your server run on 32bits, because of the fragmentation of the LOH.