Skip to content

Fix crash in pylsp_definitions on definitions without a source position#715

Open
metheoryt wants to merge 1 commit into
python-lsp:developfrom
metheoryt:fix/definitions-none-position
Open

Fix crash in pylsp_definitions on definitions without a source position#715
metheoryt wants to merge 1 commit into
python-lsp:developfrom
metheoryt:fix/definitions-none-position

Conversation

@metheoryt

Copy link
Copy Markdown

Problem

pylsp_definitions raises on some textDocument/definition requests:

TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
  File ".../pylsp/plugins/definition.py", line 69, in pylsp_definitions
    "start": {"line": d.line - 1, "character": d.column},

Reported in #623 and #624.

Root cause

The default follow_builtin_definitions is True, and the return-list filter is:

for d in definitions
if d.is_definition() and (follow_builtin_defns or _not_internal_definition(d))

_not_internal_definition(d) is the only place d.line/d.column are checked for
None, but the follow_builtin_defns or ... short-circuit means it is never
evaluated when the setting is left at its default. When jedi resolves a definition
into a compiled/builtin module, d.line and d.column are None, so d.line - 1
crashes.

Fix

Exclude definitions that have no line/column unconditionally — such a definition
cannot be expressed as a valid LSP range regardless of the
follow_builtin_definitions setting. This is a one-clause addition to the existing
filter and leaves the behaviour of builtins that do carry a position (e.g. the
builtins.pyi stub covered by test_builtin_definition) unchanged.

Test

Adds test_definition_without_source_position, which patches jedi's goto to
return a definition with line=None/column=None and asserts pylsp_definitions
returns [] instead of raising. It fails on develop (with the exact TypeError
above) and passes with this change.

Design note

I went with dropping positionless definitions since they can't form a usable LSP
location. An alternative would be to keep them and clamp to line 0 ((d.line or 1) - 1)
so navigation still lands at the top of module_path when one exists — happy to
switch to that if maintainers prefer preserving the result over dropping it.

Fixes #623
Fixes #624

When follow_builtin_definitions is True (the default), the return-list
comprehension filter short-circuits
`follow_builtin_defns or _not_internal_definition(d)`, so the None-guards
inside _not_internal_definition never run. A jedi definition that resolves
into a compiled/builtin module has line/column == None, so `d.line - 1`
raises `TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'`.

Exclude definitions with no line/column unconditionally: they cannot form a
valid LSP range regardless of the follow_builtin_definitions setting.

Fixes python-lsp#623
Fixes python-lsp#624

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
metheoryt added a commit to metheoryt/machines that referenced this pull request Jul 8, 2026
Now that the pylsp_definitions None-guard fix is committed upstream as
python-lsp/python-lsp-server#715, build python-lsp-server from that fork
commit (metheoryt/python-lsp-server @ e4ee218) rather than carrying the
change as a local .patch. Overrides src/version only and keeps nixpkgs'
own patches (jedi-compat). Verified: builds and the full test suite —
including the new in-tree regression test — passes.

Revert to plain nixpkgs once #715 merges and ships in a release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error from pylsp:TypeError: unsupported operand type(s) for -: 'NoneType' and 'int' TypeError in definition.py when handling line and column values

1 participant