UnsupportedOperatorError: Exporting the operator to ONNX opset version is not supported
Your model uses a PyTorch operation the ONNX exporter cannot translate at the chosen opset. Raise the opset version, try the newer dynamo exporter, or rewrite the offending op.
Updated
The error
torch.onnx.errors.UnsupportedOperatorError: Exporting the operator 'aten::fft_fft2' to ONNX opset version 17 is not supported. Please feel free to request support or submit a pull request on PyTorch GitHub: https://github.com/pytorch/pytorch/issues.
The operator name varies — the pattern aten::something ... not supported is the constant.
What it means
ONNX is a portable model format, and exporting means translating every PyTorch operation in your model's graph into ONNX's operator vocabulary. That vocabulary is versioned by opset — higher opsets know more operators. The exporter met an operation (aten::fft_fft2 here) with no translation at your chosen opset. One untranslatable op fails the whole export.
Why it happens
Three gaps line up: the op is newer or rarer than your opset covers; your torch version's exporter predates the translation (support grows release by release); or the op genuinely has no ONNX equivalent yet — custom ops and exotic layers live here. Models pulled from research code hit this often, since researchers never optimised for exportability.
How to fix it
1. Raise the opset and retry. Cheap and frequently sufficient:
torch.onnx.export(model, sample_input, "model.onnx", opset_version=20)Check what your runtime supports — ONNX Runtime handles current opsets, but older mobile/edge stacks may cap you lower.
2. Upgrade torch, and try the dynamo-based exporter. The newer export path (default in recent releases; explicit via dynamo=True in the 2.x line) covers substantially more of PyTorch:
torch.onnx.export(model, sample_input, "model.onnx", dynamo=True)Different tracer, different coverage — models that fail the legacy exporter often pass this one.
3. Rewrite the offending operation. Find where the named op comes from (search the model code), and substitute an exportable equivalent — for example, replacing an FFT-based layer with its spatial-domain equivalent, precomputing a constant transform, or moving the op outside the exported graph into pre/post-processing:
# preprocess outside the model, export the rest
features = torch.fft.fft2(x).abs() # runs in Python, not in ONNX
onnx_output = session.run(None, {"input": features.numpy()})Moving non-exportable work to the pipeline edges is the pragmatic pattern for deployment.
4. For ops you control, register a custom symbolic — the advanced route: map your op to existing ONNX primitives via torch.onnx.register_custom_op_symbolic. Worth it for one op in a model you will export repeatedly; overkill otherwise.
5. Reconsider whether you need ONNX at all. If the target runtime is Python with a GPU, TorchScript-free deployment via plain PyTorch (or torch.compile) may serve better than fighting an export.
How to prevent it
Export early in a project, not at the end — a tiny prototype export surfaces unsupported ops while the architecture is still cheap to change. Prefer standard layers over exotic ops when deployment is a requirement, and record the working opset and torch versions next to the export script.
Related errors
- CUDAExecutionProvider is not available — the next hurdle, running the exported model on GPU
- Some ops are not supported by the native TFLite runtime — the same wall in TensorFlow Lite
- operator torchvision::nms does not exist