You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
When producing some exception from a plain assert, the exception is modified by fastai, but the modify_exception call introduces another error, which leads to a very convoluted stack trace.
When in any callback you have an assert without description, the code which handles the exception and reraises it (i.e. e.args[0]) will itself produce another exception, because it assumes that the exception had arguments, while it didn't. Please apply the fix proposed at the bottom of this issue report.
To Reproduce
# Python
import torch
from torch.utils.data import TensorDataset
from fastai.vision.all import *
from fastai.callback.core import Callback
# Create random noise data
x = torch.randn(100, 28)
y = torch.randint(0, 2, (100,1))
# Create a TensorDataset and then a DataLoader
train_dl = DataLoader(TensorDataset(x, y.float()), batch_size=64, shuffle=True)
dls = DataLoaders(train_dl, train_dl).cuda()
# Define a custom callback
class CustomCallback(Callback):
def after_fit(self):
assert False
# Create a learner and train
learn = Learner(dls, torch.nn.Linear(28, 1), loss_func=nn.BCEWithLogitsLoss(), cbs=CustomCallback())
learn.fit(1)
Expected behavior
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[14], [line 22](vscode-notebook-cell:?execution_count=14&line=22)
[20](vscode-notebook-cell:?execution_count=14&line=20) # Create a learner and train
[21](vscode-notebook-cell:?execution_count=14&line=21) learn = Learner(dls, torch.nn.Linear(28, 1), loss_func=nn.BCEWithLogitsLoss(), cbs=CustomCallback())
---> [22](vscode-notebook-cell:?execution_count=14&line=22) learn.fit(1)
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:264](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:264), in Learner.fit(self, n_epoch, lr, wd, cbs, reset_opt, start_epoch)
[262](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:262) self.opt.set_hypers(lr=self.lr if lr is None else lr)
[263](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:263) self.n_epoch = n_epoch
--> [264](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:264) self._with_events(self._do_fit, 'fit', CancelFitException, self._end_cleanup)
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:201](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:201), in Learner._with_events(self, f, event_type, ex, final)
[199](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:199) try: self(f'before_{event_type}'); f()
[200](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:200) except ex: self(f'after_cancel_{event_type}')
--> [201](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:201) self(f'after_{event_type}'); final()
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:172](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:172), in Learner.__call__(self, event_name)
--> [172](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:172) def __call__(self, event_name): L(event_name).map(self._call_one)
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/foundation.py:156](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/foundation.py:156), in L.map(self, f, *args, **kwargs)
--> [156](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/foundation.py:156) def map(self, f, *args, **kwargs): return self._new(map_ex(self, f, *args, gen=False, **kwargs))
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:840](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:840), in map_ex(iterable, f, gen, *args, **kwargs)
[838](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:838) res = map(g, iterable)
[839](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:839) if gen: return res
--> [840](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:840) return list(res)
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:825](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:825), in bind.__call__(self, *args, **kwargs)
[823](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:823) if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
[824](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:824) fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
--> [825](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:825) return self.func(*fargs, **kwargs)
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:176](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:176), in Learner._call_one(self, event_name)
[174](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:174) def _call_one(self, event_name):
[175](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:175) if not hasattr(event, event_name): raise Exception(f'missing {event_name}')
--> [176](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:176) for cb in self.cbs.sorted('order'): cb(event_name)
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:62](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:62), in Callback.__call__(self, event_name)
[60](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:60) try: res = getcallable(self, event_name)()
[61](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:61) except (CancelBatchException, CancelBackwardException, CancelEpochException, CancelFitException, CancelStepException, CancelTrainException, CancelValidException): raise
---> [62](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:62) except Exception as e: raise modify_exception(e, f'Exception occured in `{self.__class__.__name__}` when calling event `{event_name}`:\n\t{e.args[0]}', replace=True)
[63](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:63) if event_name=='after_fit': self.run=True #Reset self.run to True at each end of fit
[64](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:64) return res
File [~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:60](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:60), in Callback.__call__(self, event_name)
[58](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:58) res = None
[59](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:59) if self.run and _run:
---> [60](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:60) try: res = getcallable(self, event_name)()
[61](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:61) except (CancelBatchException, CancelBackwardException, CancelEpochException, CancelFitException, CancelStepException, CancelTrainException, CancelValidException): raise
[62](https://file+.vscode-resource.vscode-cdn.net/home/tim.kuipers/dev/deeplearning/projects/iris_drone_classification/pipeline_2023_fastai2/~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:62) except Exception as e: raise modify_exception(e, f'Exception occured in `{self.__class__.__name__}` when calling event `{event_name}`:\n\t{e.args[0]}', replace=True)
Cell In[14], [line 18](vscode-notebook-cell:?execution_count=14&line=18)
[17](vscode-notebook-cell:?execution_count=14&line=17) def after_fit(self):
---> [18](vscode-notebook-cell:?execution_count=14&line=18) assert False, "SDg"
AssertionError: Exception occured in `CustomCallback` when calling event `after_fit`
Actual behavior
{
"name": "IndexError",
"message": "tuple index out of range",
"stack": "---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:60, in Callback.__call__(self, event_name)
59 if self.run and _run:
---> 60 try: res = getcallable(self, event_name)()
61 except (CancelBatchException, CancelBackwardException, CancelEpochException, CancelFitException, CancelStepException, CancelTrainException, CancelValidException): raise
Cell In[15], line 18, in CustomCallback.after_fit(self)
17 def after_fit(self):
---> 18 assert False
AssertionError:
During handling of the above exception, another exception occurred:
IndexError Traceback (most recent call last)
Cell In[15], line 22
20 # Create a learner and train
21 learn = Learner(dls, torch.nn.Linear(28, 1), loss_func=nn.BCEWithLogitsLoss(), cbs=CustomCallback())
---> 22 learn.fit(1)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:264, in Learner.fit(self, n_epoch, lr, wd, cbs, reset_opt, start_epoch)
262 self.opt.set_hypers(lr=self.lr if lr is None else lr)
263 self.n_epoch = n_epoch
--> 264 self._with_events(self._do_fit, 'fit', CancelFitException, self._end_cleanup)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:201, in Learner._with_events(self, f, event_type, ex, final)
199 try: self(f'before_{event_type}'); f()
200 except ex: self(f'after_cancel_{event_type}')
--> 201 self(f'after_{event_type}'); final()
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:172, in Learner.__call__(self, event_name)
--> 172 def __call__(self, event_name): L(event_name).map(self._call_one)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/foundation.py:156, in L.map(self, f, *args, **kwargs)
--> 156 def map(self, f, *args, **kwargs): return self._new(map_ex(self, f, *args, gen=False, **kwargs))
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:840, in map_ex(iterable, f, gen, *args, **kwargs)
838 res = map(g, iterable)
839 if gen: return res
--> 840 return list(res)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastcore/basics.py:825, in bind.__call__(self, *args, **kwargs)
823 if isinstance(v,_Arg): kwargs[k] = args.pop(v.i)
824 fargs = [args[x.i] if isinstance(x, _Arg) else x for x in self.pargs] + args[self.maxi+1:]
--> 825 return self.func(*fargs, **kwargs)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/learner.py:176, in Learner._call_one(self, event_name)
174 def _call_one(self, event_name):
175 if not hasattr(event, event_name): raise Exception(f'missing {event_name}')
--> 176 for cb in self.cbs.sorted('order'): cb(event_name)
File ~/miniforge3/envs/dl/lib/python3.11/site-packages/fastai/callback/core.py:62, in Callback.__call__(self, event_name)
60 try: res = getcallable(self, event_name)()
61 except (CancelBatchException, CancelBackwardException, CancelEpochException, CancelFitException, CancelStepException, CancelTrainException, CancelValidException): raise
---> 62 except Exception as e: raise modify_exception(e, f'Exception occured in `{self.__class__.__name__}` when calling event `{event_name}`:\
\\t{e.args[0]}', replace=True)
63 if event_name=='after_fit': self.run=True #Reset self.run to True at each end of fit
64 return res
IndexError: tuple index out of range"
}
Additional context
Fix the following code in core.py:
# %% ../../nbs/13_callback.core.ipynb 16
@funcs_kwargs(as_method=True)
class Callback(Stateful,GetAttr):
[...]
def __call__(self, event_name):
"Call `self.{event_name}` if it's defined"
_run = (event_name not in _inner_loop or (self.run_train and getattr(self, 'training', True)) or
(self.run_valid and not getattr(self, 'training', False)))
res = None
if self.run and _run:
try: res = getcallable(self, event_name)()
except (CancelBatchException, CancelBackwardException, CancelEpochException, CancelFitException, CancelStepException, CancelTrainException, CancelValidException): raise
except Exception as e: raise modify_exception(e, f'Exception occured in `{self.__class__.__name__}` when calling event `{event_name}`:\n\t{e.args[0]}', replace=True)
Code fix suggested by GPT:
try:
res = getcallable(self, event_name)()
except (CancelBatchException, CancelBackwardException, CancelEpochException, CancelFitException, CancelStepException, CancelTrainException, CancelValidException):
raise
except Exception as e:
error_message = e.args[0] if e.args else str(e)
raise modify_exception(e, f'Exception occured in `{self.__class__.__name__}` when calling event `{event_name}`:\n\t{error_message}', replace=True)
The text was updated successfully, but these errors were encountered:
In my current project I am hitting an assert failure from fastai itself: assert self.monitor in self.recorder.metric_names[1:]. However, my debugger is not able to follow the exception, because of the issue described in this ticket. This means I cannot debug the issue.
Besides fixing this ticket, you might also want to check all your asserts to see if they have a message associated with them.
fastai 2.7.14
fastcore 1.5.29
Describe the bug
When producing some exception from a plain assert, the exception is modified by fastai, but the modify_exception call introduces another error, which leads to a very convoluted stack trace.
When in any callback you have an assert without description, the code which handles the exception and reraises it (i.e.
e.args[0]
) will itself produce another exception, because it assumes that the exception had arguments, while it didn't. Please apply the fix proposed at the bottom of this issue report.To Reproduce
Expected behavior
Actual behavior
Additional context
Fix the following code in core.py:
Code fix suggested by GPT:
The text was updated successfully, but these errors were encountered: