NVIDIA-Merlin / NVIDIA-Merlin/Transformers4Rec

[BUG] `Head.build` raises `TypeError: 'NoneType' object is not callable` when body lacks `output_size`

Open Beginner friendly
#811 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.3k
Forks
165
Avg merge
1m
Merged PRs (30d)
2

Description

Bug description

PR #802 (commit ab7207cf, "Sec pic fix") changed the default sentinel in transformers4rec/torch/model/base.py from lambda: None to None:

https://github.com/NVIDIA-Merlin/Transformers4Rec/blob/8bf122f5dcb39feecfc6dabde734d79c2d1c4380/transformers4rec/torch/model/base.py#L288

if not getattr(self.body, "output_size", None)():
    raise ValueError(
        "Can't infer output-size of the body, please provide  "
        "a `Block` with a output-size. You can wrap any torch.Module in a Block."
    )

When self.body does not have an output_size attribute, getattr(..., None) returns None, and the trailing () then evaluates None(), which raises TypeError: 'NoneType' object is not callable.

The original lambda: None sentinel was callable and returned a falsy value, so the intended raise ValueError(...) path below was actually reached. The current code path short-circuits with the wrong exception type, making the error message unactionable.

This is not caught by tests because all fixtures provide bodies with output_size.

Steps/Code to reproduce bug
class Body:
    pass

body = Body()
getattr(body, "output_size", None)()
# TypeError: 'NoneType' object is not callable

Versus the pre-#802 behavior:

getattr(body, "output_size", lambda: None)()
# None   (falsy, falls through to `raise ValueError(...)` in Head.build)
Expected behavior

When the body lacks output_size, Head.build should raise the original ValueError("Can't infer output-size of the body ...") so the user gets a clear, actionable message.

Environment details
  • Transformers4Rec: main @ 8bf122f5 (regression introduced by PR #802 / commit ab7207cf)
  • Python: any
Additional context

Two equivalent minimal fixes:

Option A — restore the callable sentinel:

if not getattr(self.body, "output_size", lambda: None)():

Option B — explicit two-step check (slightly more readable):

output_size_fn = getattr(self.body, "output_size", None)
if output_size_fn is None or not output_size_fn():
    raise ValueError(...)

Option A preserves behavior byte-for-byte. Happy to send a PR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in transformers4rec/torch/model/base.py at Head.build and reproduce the failure with a body that lacks output_size. Verify that the missing attribute reaches the intended ValueError path with its actionable message, and add regression coverage for this case alongside the existing model tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
machine-learning
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.