How can code continue when an error happens

Dear friends, I try to add a face but 4 points are in a line so I received following error.
“Error: #<ArgumentError: Cannot convert argument to Geom::Point3d>”
Is it possible codes continue and I do something when I receive this error. Something like following codes.

face1 = grp.entities.add_face [pt1, pt2, pt4, pt3]
if ArgumentError
  p "ArgumentError"
else
 #do something
end

This question is for all kind of errors that we received and we don’t want codes terminated.
Thank you in advance.

Read the primer on handling exceptions …
https://ruby-doc.org/core-2.7.1/doc/syntax/exceptions_rdoc.html

face1 = grp.entities.add_face [pt1, pt2, pt4, pt3]
rescue ArgumentError => err
if err.message.start_with?("Cannot convert")
  p "Argument Error"
else
#do something
end

Thank you so much Dan. Please confirm code is right. Also confirm we can use such solution for all errors.

  • a) " Exceptions are rescued in a begin / end block. "
    I don’t see any “begin” above.

  • b) " If you are inside a method, you do not need to use begin or end unless … "
    I don’t see any method defined.

  • c) You did not take into consideration the warning from ene_su from that topic where you “copied” the code from.

1 Like
def my_method
  # ...
rescue
  # ...
end

my code is a part of definition.

def make_stair
  #
  face1 = grp.entities.add_face [pt1, pt2, pt4, pt3]
  rescue ArgumentError => err
  if err.message.start_with?("Cannot convert")
    p "Argument Error"
  else
  #do something
  end
  #
end

Thank you for your reminder.

Just saying…(if you want to deal with the message text)

Be aware that for example the #add_face method can generate different message text for ArgumentError, e.g:
Points are not planar...
Duplicate points in array...
Not enough edges...

Then a TypeError can raised, like
wrong argument type...

(But I’m also just try to learn :wink: )

1 Like

Your indentation is incorrect. The rescue should be at the same level as it’s begin or the def.

Even though technically Christina is correct, the API authors decided not to create API specific exception classes (which was a poor decision,) … so the only way we have to differentiate the various exceptions is by the generated message of the standard exceptions raised.

1 Like

Given that error messages may be localized, if the API had specific error classes (maybe for the factory methods) that returned a number, that might be helpful…

1 Like

SketchUp API error messages are not localized, but they could. Or the English error messages could be reworded in the next version.

  • You can avoid specific errors from happening with validation of the user input (e.g. if points are planar) and then give feedback to the user and do an “early exit” from the method.

  • If you want to narrow down the type of error, but the error class is not specific enough, you can make a begin rescue end block very close around that single method call where you expect errors. This way you can be sure that the ArgumentError does not come from another method call above. You can make nested rescue blocks, for example keep the outer one for general errors.

    begin
      face1 = grp.entities.add_face [pt1, pt2, pt4, pt3]
    rescue ArgumentError => err
      # This ArgumentError can only come from add_face
      # do something
    end
    
  • Do not handle errors when you don’t know how your application/extension can proceed. For example if you cannot think of any alternative way to add a face for these points, then you actually cannot handle this error. Then you can only exit the method and let the user know why the expected action does not happen.

    This was probably just a placeholder. If you would do this you would get less information than from the original ArgumentError because it had a precise message and a very useful backtrace that points you to the exact location. (For this reason, never try to make errors completely silent.) Somewhat more useful is:

    puts(err.message)
    puts(err.backtrace.join($/))
    

    (Should actually be printed to $stderr, but SketchUp doesn’t implement puts on it?)

1 Like

Lets look at what the Ruby Core docs suggest …

Exception class : Custom Exceptions

A good practice is for a library to create a single “generic” exception class (typically a subclass of StandardError or RuntimeError) and have its other exception classes derive from that class. This allows the user to rescue the generic exception, thus catching all exceptions the library may raise even if future versions of the library add new exception subclasses.

So I’d would think that there would be some kind of general SketchUp application exception super class (which would be a subclass of StandardError,) OR as I’ve said in previous discussions I suggested that there be a dedicated Sketchup::Exception submodule that could encapsulate all the API exceptions so that they are not scattered throughout the documentation as they are in the Ruby core.

Then within this module could reside subclasses of that would be categorical and say descendants of a Sketchup::Exception::ArgumentError:

Sketchup::GeometryError for an example.
Beneath this, specific subclasses such as:

  • Sketchup::Exception::NonPlanarPointsError
  • Sketchup::Exception::DuplicatePointsError
  • Sketchup::Exception::NotEnoughEdgesError
    etc.

But then the API has to define constants for these “error codes”. (It already takes this approach for some API functionality.)

But in my mind, I don’t see the benefit of this route when the simple definition of an exception subclass is the recommended way. (Ie, … a class identifier is a constant reference.)

The docs says …

An Exception object carries information about an exception:

  • Its type (the exception’s class).
  • An optional descriptive message.
  • Optional backtrace information.

So the exception’s class name is the only thing required.

2 Likes

Can you show me in an example? Thank you in advance.

You are right it is just a place holder. In face when I find this error, I will delete group send message to user that your step information is wrong (one step cannot have 4 points in one line) and back to begin of codes. I just try to ask my question as simple as possible. Using exceptions can help us to save codes.

1 Like

Very interesting thoughts!
But if you try to catch all sorts of ArgumentError you would miss Sketchup::Exception::ArgumentError. A case for multiple inheritance or mixins?

It can be very complex so let me give you an example. I try to make stair by codes. When user draw a possible stair, no error happen but when user draw an impossible stair I receive error when draw face1. following you can see an example for impossible stair. I check many times and error just happen when logically stair cannot exist. One solution is I try to limit user for this error that will have many different condition and I should write some codes for each one and other solution is using this error.

Well of course this one might need to be a subclass of ArgumentError (which is one of the subclasses of StandardError.)

But it is unlikely after 20 years that they’ll change course and create more API classes. (So we are probably just wasting our time fantasizing about it.)

Yes you need to use input validation on the values from your input box fields to prevent the user from drawing invalid stair configurations. You test the input values before your code attempts to draw geometry, and if the values are bad then you display a error message box to the user and redisplay the input box.

1 Like