# Handling Errors in Perspective

**URL:** <https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671>\
**Category:** Ignition\
**Tags:** perspective, scripting\
**Created:** [April 16, 2021, 3:07am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671 "2021-04-16T03:07:01Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![DougSN](https://avatars.discourse-cdn.com/v4/letter/d/a9adbd/32.png) [@DougSN](https://forum.inductiveautomation.com/u/DougSN)\
**Post date:** [April 16, 2021, 3:07am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/1 "2021-04-16T03:07:01Z")

</div>

In Perspective, I have had trouble with errors not being raised to the user. If I am in a Designer and I execute a button click or something, any errors will pop up in an Error window and print to the console. But if I launch a browser to that page, errors are not raised to be visible to the user.

If I were to set up a data entry screen and then create a Submit button using a button component, I would set up some scripting in the onActionPerformed event of that button to send the data to the database. If there was some problem inserting into the database, the user would not know.

What is the typical method for setting up error handling so that the user would find out there is a problem in this example?

---

<div class="post-metadata">

**Author:** ![cmallonee](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/cmallonee/32/6416_2.png) [@cmallonee](https://forum.inductiveautomation.com/u/cmallonee)\
**Post date:** [April 16, 2021, 3:15am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/2 "2021-04-16T03:15:44Z")

</div>

If it’s something you need to alert the user about, I would wrap your logic in a try/except block, and in the exception handling you should use `system.perspective.openPopup()`. You’ll want to create a View which is able to convey information to the user, whether it the stacktrace or just a warning that something failed.

---

<div class="post-metadata">

**Author:** ![DougSN](https://avatars.discourse-cdn.com/v4/letter/d/a9adbd/32.png) [@DougSN](https://forum.inductiveautomation.com/u/DougSN)\
**Post date:** [April 16, 2021, 8:08pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/3 "2021-04-16T20:08:48Z")

</div>

That sounds simple enough, thank you.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 7, 2023, 9:57am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/4 "2023-01-07T09:57:23Z")

</div>

Hi [cmallonee](https://forum.inductiveautomation.com/u/cmallonee), I'm doing as suggested. To the popup window I'm passing the traceback.

On a View component

```python
def runAction(self, event):
	try:
		_.update_db_with_error()
	except:
		_.error(self)

```

Script module

```python
def error(_self):
	if _self.session.props.device.type == 'designer':
		raise
	
	params = {'message': traceback.format_exc()}
	system.perspective.openPopup(
		'random_id',
		'Popup/ErrorMessage',
		params=params,
		title='EXECUTION ERROR: contact developers',
		modal=True
	)

```

I noticed that if I'm NOT using `try/catch` on the View component I'm getting native error window with full traceback which includes the cause (which is sooo good) of the exception, like this

```plaintext
caused by SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`mes`.`product_code_line`, CONS.....

```

But when I'm using `try/catch` with `traceback.format_exc()` it cuts the trace and last message is

```plaintext
line 122, in update_db Exception: java.lang.Exception: Error executing system.db.runPrepUpdate(DELETE FROM product_code WHERE id = ?, [25], db_con, , false, false)

```

Is there the way to capture full exception trace by `traceback.format_exc()` as same as the native error window?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 9, 2023, 8:15pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/5 "2023-01-09T20:15:22Z")

</div>

Jython's bare `except` won't catch Java exceptions, for complicated reasons. You must add an additional catch clause:

> [@system.db.runUpdateQuery Exception Handling](https://forum.inductiveautomation.com/t/system-db-runupdatequery-exception-handling/68237/2):
>
> Normal jython try: -- except: won't trap java exceptions. You often need two except: clauses, the first being except java.lang.Throwable, t: or similar. Some [related discussions](https://forum.inductiveautomation.com/search?q=Throwable%20%40pturmel). Note that when catching such exceptions in Vision Client scope or Designer scope, the real SQL exception is not available--it won't serialize and the JDBC classes don't exist in those scopes anyways.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 11, 2023, 3:32am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/6 "2023-01-11T03:32:51Z")

</div>

Thank you [PGriffith](https://forum.inductiveautomation.com/u/PGriffith)

Bare `except` in the code above catches the same error with the same traceback as `java.lang.Throwable`. If it'll be an any chance to catch "the real SQL" exception in python script, it would be great.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 11, 2023, 1:01pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/7 "2023-01-11T13:01:26Z")

</div>

In gateway scope, you get the real SQL exception. Possibly as a chained cause. Those exceptions are not serializable (at least, not without the same JDBC drivers in the receiving scope), so they get summarized in Vision Client scope and Designer Scope.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 11, 2023, 9:43pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/8 "2023-01-11T21:43:00Z")

</div>

It seems like it is impossible to get the chained cause (the SQL exception) to the Designer Scope using python.

Is there any news from the Ignition dev team on solving this? As a temp fix it would be good to concat the message of the chained cause to the `java.lang.Throwable` message.

We're planning to completely migrate to Perspective and we'll need to get the actual cause message to the logs and on the screen for faster troubleshooting.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 11, 2023, 10:03pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/9 "2023-01-11T22:03:11Z")

</div>

It will never be solved, because those classes are only available in the gateway.

Consider using a gateway message handler to run your SQL, and that will be able to analyze any exceptions completely. Use `system.util.sendRequest()` from Vision or Designer scope to run the handler.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 11, 2023, 10:03pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/10 "2023-01-11T22:03:52Z")

</div>

> [@Alex\_SHARIKOV](#):
>
> We're planning to completely migrate to Perspective

Perspective runs in gateway scope, so the complete message should be available there.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 11, 2023, 10:10pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/11 "2023-01-11T22:10:02Z")

</div>

What's the best way to catch errors in Perspective? What was I doing wrong in the code above 👆 (4th message from the top) [Handling Errors in Perspective - #4 by Alex\_SHARIKOV](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/4)

The goal is to `catch` the entire error message including the SQL cause.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 11, 2023, 10:23pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/12 "2023-01-11T22:23:08Z")

</div>

Jython's traceback module doesn't do java causes. You need to use java except clauses, and use java's stack trace tools. See my post that Paul linked above.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 11, 2023, 11:29pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/13 "2023-01-11T23:29:49Z")

</div>

How python's `catch` should look like? Do I do it incorrectly below?

This is a script on Perspective button `onActionPerformed`:

```python
def runAction(self, event):
	import java
	
	try:
		_.update_db_with_error()
		
	except java.lang.Exception as e:
		system.perspective.print('java.lang.Exception')
		system.perspective.print(e)
		
	except java.lang.Throwable as e:
		system.perspective.print('java.lang.Throwable')
		system.perspective.print(e)

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 12, 2023, 1:43am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/14 "2023-01-12T01:43:54Z")

</div>

`java.lang.Exception` is a subclass of `java.lang.Throwable`, so that is redundant. If you look at the linked examples scattered over this forum, one `except` clause catches **jython's** Exception, the other catches **java's** Throwable. But printing a throwable (or java's exception) does not include the `cause`. Use the throwable's [printStackTrace()](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Throwable.html#printStackTrace(java.io.PrintStream)) method to get everything.

{ You've responded to the linked post above, so I would presume you've followed the links to related discussions therein? }

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 12, 2023, 8:53am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/15 "2023-01-12T08:53:36Z")

</div>

I've read the suggested links but didn't understand how to implement it. Thank you for your guidance. My code so far:

View component

```python
def runAction(self, event):
	try:
		_.update_db_with_error()
	except:
		_.error(self)

```

and my script module:

```python
def error(_self):
	ex_type, ex, stacktrace = sys.exc_info()
	
	is_java_ex = type(ex_type) == type(java.lang.Exception)
	cause = str(ex.getCause()) + ' *****' if is_java_ex else ''
	
	if _self.session.props.device.type == 'designer':
		raise Exception, (cause, ex), stacktrace

		
	trigger = ' ***** by ' + _self.name + ' from ' + _self.page.props.path
	
	message = cause + traceback.format_exc() + trigger
	params = {'message': message}
	log(message, 'error')
	system.perspective.openPopup(
		'random_id',
		'Popup/ErrorMessage',
		params=params,
		title='EXECUTION ERROR: Contact developers',
		modal=True
	)

```

not sure if this is an efficient way but it shows me the desired traceback and the cause in Perspective and in Designer for both jython errors and the `Throwable`s

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [January 12, 2023, 3:00pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/16 "2023-01-12T15:00:33Z")

</div>

> [@Alex\_SHARIKOV](#):
>
> ```auto
> def runAction(self, event):
> try:
> _.update_db_with_error()
> except:
> _.error(self)
> 
> ```

I _think_ you will need to do this. @pturmel is usually the exception wizard.

```auto
def runAction(self, event):
	from java.lang import Throwable
	try:
		_.update_db_with_error()
	except Exception, e:
		_.error(self,e)
	except Throwable, t:
		_.error(self,t)

```

You will need to modify the error function to take in that error. Then check the type in the function.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 12, 2023, 11:44pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/17 "2023-01-12T23:44:16Z")

</div>

Yes, he is, he helped me understand it more.

That's what I'm doing in the script module. At line

```python
is_java_ex = type(ex_type) == type(java.lang.Exception)

```

I check if it is `Throwable` and then take appropriate action.

The reason I'm doing it that way is that I prefer to keep the View code is tidy as possible. The `except:` below will catch all errors and I deal with them in the `_.error(self)` function.

> [@Alex\_SHARIKOV](#):
>
> ```auto
> try:
> _.update_db_with_error()
> except:
> _.error(self)
> 
> ```

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [January 12, 2023, 11:58pm UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/18 "2023-01-12T23:58:21Z")

</div>

I may be wrong... But Im not sure that's how jython works. A naked except will only catch python errors. You must add the second except for the Java exceptions. I've never seen it work another way.

---

<div class="post-metadata">

**Author:** ![Alex\_SHARIKOV](https://avatars.discourse-cdn.com/v4/letter/a/a183cd/32.png) [@Alex\_SHARIKOV](https://forum.inductiveautomation.com/u/Alex_SHARIKOV)\
**Post date:** [January 13, 2023, 12:33am UTC](https://forum.inductiveautomation.com/t/handling-errors-in-perspective/45671/19 "2023-01-13T00:33:10Z")

</div>

Seems like it does. I've tested this approach with Java and Python exceptions.  
Now I get both types, including Java cause, in Error window when working with the Designer and in Perspective Popup I have the traceback with the Java cause.

I used _Developer Guid for Jython_ at [Chapter 7: Exception Handling and Debugging — Definitive Guide to Jython latest documentation](https://jython.readthedocs.io/en/latest/ExceptionHandlingDebug/) in particular `Example 5-2: Using sys.exc_info()`
