diff --git a/bt5/erp5_data_notebook/ExtensionTemplateItem/portal_components/extension.erp5.JupyterCompile.py b/bt5/erp5_data_notebook/ExtensionTemplateItem/portal_components/extension.erp5.JupyterCompile.py
index 96d12aef5b2e06daed8dc6ba2da6d9ac1ad5c98f..e49fc9223949eadf783c057ad043591a9b2ddbc6 100644
--- a/bt5/erp5_data_notebook/ExtensionTemplateItem/portal_components/extension.erp5.JupyterCompile.py
+++ b/bt5/erp5_data_notebook/ExtensionTemplateItem/portal_components/extension.erp5.JupyterCompile.py
@@ -195,7 +195,16 @@ def Base_runJupyterCode(self, jupyter_code, old_notebook_context):
     import_fixer = ImportFixer()
     environment_collector = EnvironmentParser()
     ast_node = import_fixer.visit(ast_node)
-    ast_node = environment_collector.visit(ast_node)
+    
+    # The collector also raises errors when environment.define and undefine
+    # calls are made incorrectly, so we need to capture them to propagate
+    # to Jupyter for rendering.
+    try:
+      ast_node = environment_collector.visit(ast_node)
+    except (EnvironmentDefinitionError, EnvironmentUndefineError) as e:
+      transaction.abort()
+      return getErrorMessageForException(self, e, notebook_context)
+      
     
     # Get the node list from the parsed tree
     nodelist = ast_node.body
@@ -277,7 +286,17 @@ def Base_runJupyterCode(self, jupyter_code, old_notebook_context):
             break
         if not found:
           transaction.abort()
-          raise Exception("Trying to remove non existing function/variable from environment: '%s'\nEnvironment: %s" % (func_alias, str(notebook_context['setup'])))
+          result = {
+            'result_string': "EnvironmentUndefineError: Trying to remove non existing function/variable from environment: '%s'\n" % func_alias,
+            'notebook_context': notebook_context,
+            'status': 'ok',
+            'mime_type': 'text/plain',
+            'evalue': None,
+            'ename': None,
+            'traceback': None,
+          }
+          return result
+            
       
       # Removing all the setup functions if user call environment.clearAll()
       if environment_collector.clearAll():
@@ -402,6 +421,14 @@ def Base_runJupyterCode(self, jupyter_code, old_notebook_context):
   return result
 
 
+class EnvironmentUndefineError(TypeError):
+  pass
+
+
+class EnvironmentDefinitionError(TypeError):
+  pass
+
+
 def canSerialize(obj):
   result = False
         
@@ -429,7 +456,7 @@ def canSerialize(obj):
       try:
         writer.serialize(obj)
       # Because writer.serialize(obj) relies on the implementation of __getstate__
-      # of obj, all errors can happen, so the "except all" is necessary here. 
+      # of obj, all errors can happen, so the "except all" is necessary here.
       except:
         return False
     return True
@@ -503,11 +530,20 @@ class EnvironmentParser(ast.NodeTransformer):
           name = attribute.id
           if name == 'environment' and function.attr == 'define' and not value.keywords:
             if not len(value.args) == 2:
-              message = (
-                'Not enough arguments for environment definition. Function '
-                'name and alias are required.'
-              )
-              raise Exception(message)
+              raise EnvironmentDefinitionError('environment.define calls receive 2 arguments')
+              
+            self._ensureType(
+              obj=value.args[0], 
+              klass=ast.Name, 
+              error_message='Type mismatch. environment.define receives a function as first argument.'
+            )
+            
+            self._ensureType(
+              obj=value.args[1], 
+              klass=ast.Str, 
+              error_message='Type mismatch. environment.define receives a string as second argument.'
+            )
+            
             func_name = value.args[0].id
             func_alias = value.args[1].s
             function_node = self.function_dict[func_name]
@@ -532,6 +568,13 @@ class EnvironmentParser(ast.NodeTransformer):
               arg_value = node_value_dict[type(arg_value_node)](arg_value_node)
               self.environment_var_dict[arg_name] = arg_value
           elif name == 'environment' and function.attr == 'undefine':
+            self._ensureType(
+              obj=value.args[0], 
+              klass=ast.Str, 
+              call_type='undefine',
+              error_message='Type mismatch. environment.undefine receives only a string as argument.'
+            )
+            
             func_alias = value.args[0].s
             self.environment_remove_list.append(func_alias)
           elif name == 'environment' and function.attr == 'clearAll':
@@ -540,6 +583,14 @@ class EnvironmentParser(ast.NodeTransformer):
             self.show_environment_setup = True
     return node
     
+  def _ensureType(self, obj=None, klass=None, error_message=None, call_type='define'):
+    if not isinstance(obj, klass):
+      if call_type == 'define':
+        error_class = EnvironmentDefinitionError
+      elif call_type == 'undefine':
+        error_class = EnvironmentUndefineError
+      raise error_class(error_message)
+    
   def clearAll(self):
     return self.environment_clear_all
     
@@ -912,4 +963,3 @@ def erp5PivotTableUI(self, df):
   iframe_host = self.REQUEST['HTTP_X_FORWARDED_HOST'].split(',')[0]
   url = "https://%s/erp5/Base_displayPivotTableFrame?key=%s" % (iframe_host, key)
   return IFrame(src=url, width='100%', height='500')
-
diff --git a/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.py b/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.py
index 62a89e23d1717b8d178b397bc23bcc49897851a8..a97ccf2153dc2d543417b9023c31358878e57661 100644
--- a/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.py
+++ b/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.py
@@ -614,6 +614,69 @@ print random.randint(1,1)
     self.assertEquals(result['status'], 'ok')
     self.assertEquals(result['code_result'].strip(), '1')
     
+  def testEnvorinmentUndefineErrors(self):
+    """
+      Tests if environment.undefine wrong usage errors are correctly captured 
+      and rendered in Jupyter.
+    """
+    self.login('dev_user')
+    undefine_not_found = 'environment.undefine("foobar")' 
+    
+    reference = 'Test.Notebook.EnvironmentObject.Errors.Undefine'
+    result = self.portal.Base_executeJupyter(
+      reference=reference,
+      python_expression=undefine_not_found
+    )
+    self.tic()
+    
+    error_substring = 'EnvironmentUndefineError: Trying to remove non existing'
+    self.assertTrue(error_substring in result)
+    
+    not_string_code = 'def foobar(): pass\nenvironment.undefine(foobar)'
+    
+    reference = 'Test.Notebook.EnvironmentObject.Errors.Undefine'
+    result = self.portal.Base_executeJupyter(
+      reference=reference,
+      python_expression=not_string_code
+    )
+    self.tic()
+    
+    error_substring = 'EnvironmentUndefineError: Type mismatch.'
+    self.assertTrue(error_substring in result)
+    
+  def testEnvironmentDefineErrrors(self):
+    """
+      Tests if environment.define wrong usage errors are correctly captured 
+      and rendered in Jupyter.
+    """
+    self.login('dev_user')
+    
+    first_arg_type_code = "environment.define('foobar', 'foobar')" 
+    
+    reference = 'Test.Notebook.EnvironmentObject.Errors.Define'
+    result = self.portal.Base_executeJupyter(
+      reference=reference,
+      python_expression=first_arg_type_code
+    )
+    self.tic()
+    
+    error_substring = 'EnvironmentDefinitionError: Type mismatch'
+    self.assertTrue(error_substring in result)
+    self.assertTrue('first argument' in result)
+    
+    second_arg_type_code = 'def couscous(): pass\nenvironment.define(couscous, 123)'
+    
+    reference = 'Test.Notebook.EnvironmentObject.Errors.Define'
+    result = self.portal.Base_executeJupyter(
+      reference=reference,
+      python_expression=second_arg_type_code
+    )
+    self.tic()
+    
+    error_substring = 'EnvironmentDefinitionError: Type mismatch'
+    self.assertTrue(error_substring in result)
+    self.assertTrue('second argument' in result)
+    
   def testPivotTableJsIntegration(self):
     '''
       This test ensures the PivotTableJs user interface is correctly integrated
diff --git a/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.xml b/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.xml
index 0ee0ffb3cb46d9d4d38509db33c49f74dab2b563..da6b536c2413c01ff648198f598d59d563591d52 100644
--- a/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.xml
+++ b/bt5/erp5_data_notebook/TestTemplateItem/portal_components/test.erp5.testExecuteJupyter.xml
@@ -44,7 +44,7 @@
             <key> <string>text_content_warning_message</string> </key>
             <value>
               <tuple>
-                <string>W:457,  4: Unused variable \'notebook\' (unused-variable)</string>
+                <string>W:697,  4: Unused variable \'notebook\' (unused-variable)</string>
               </tuple>
             </value>
         </item>