Robot Listener, listener v2 on keyword fail status generates a lot of screenshots instead of one

Hello,
I used Robot Framework listener V2 to capture the current url and screen shot if the status of the current keyword is FAIL. So my code is something like this

class RobotListenerV2:
    ROBOT_LISTENER_API_VERSION = 2
    ROBOT_LIBRARY_SCOPE = "GLOBAL"    
    def end_keyword(self, name, attrs):
        # print('-------------------------------------------------------')
        # print('END keyword NAME => {} and ATTRIBUTES => {}'.format(name, attrs))
        #print('END keyword NAME => {} and ATTRIBUTES => {}'.format(name, attrs['status']))
        # print('-------------------------------------------------------')

        if attrs['status'] == 'FAIL' and attrs['status'] != 'NOT RUN':
            current_directory = os.getcwd()
            try:
                image_folder = ''
                variables = BuiltIn().get_variables()
                for k, v in variables.items():
                    if 'OUTPUT_DIR' in k:
                        image_folder = v
                time_ = round(time.time() * 1000)
                if ' ' in image_folder:
                    image_folder = image_folder.replace(' ','')
                if not os.path.exists(os.path.join(current_directory, image_folder)):
                     os.makedirs(os.path.join(current_directory, image_folder))
                image_name = self.full_screen(image_folder)
                url = self.get_web_driver_instance().current_url

                data_uri = base64.b64encode(open(image_name, 'rb').read()).decode('utf-8')
                logger.info(
                    '<tr><td colspan="3">'
                    '<a '
                    f'href="data:image/png;base64,{data_uri}">'
                    '<img '
                    f'src="data:image/png;base64,{data_uri}" width="{800}px">'
                    '</a></td></tr>',
                    html=True,
                )
                logger.info('<td class="message"><a href="{}">"{}"</a></td>'.format(url, url), html=True)
                logger.info('<td class="message">Keyword Name : {} and attributes : {}</td>'.format(name, attrs), html=True)
            except Exception as ex:
                print("We have Exception:", type(ex))
                print("We have Exception:", repr(ex))
                if hasattr(ex, 'message'):
                    print(ex.message)
                else:
                    print(ex)
            finally:
                  pass
            

What I found is that Robot Framework takes a lot of screenshot starting from the current keyword until his parent keyword. But what I want is only one screenshot for the current keyword. Any Idea on how to restrict taking screenshot for the only failing keyword? If you need an extra details I will put a complete example

I guess the issue of “multiple” screenshots depends on your code ?

If you have a keyword xxx that calls keyword yyy and yyy fails, xxx also fails too unless you dont catch the failure in there.

I’ve dealt around this sort of issue but having a LIFO stack for the testsuite → testcase → keyword calls and only reach on failure state only when on top of the stack and once the failure is handled (eg, in your case, screenshot taken), do not do it again …

Maybe attrs would also indicate what is the rootcause of the failure but dont have time to check that now.

Can you please how did you your LIFO stack.
Thank you for your reply.

When suite start is called → add suite to stack
when testcase start is called → add testcase to stack
when keyword starts → add keyword to stack …
when keyword starts → add keyword to stack …
when keyword starts → add keyword to stack …

IF keyword now fails → it should be the topmost keyword in that stack …
then each following end keyword callback already knows that “if they are part of already failed stack”, there’s no need to to react to it.

Yes understood now, thank you very much for your help @rasjani .