Skip to content

fix(tortoiseorm): avoid IndexError in _do_execute for empty/whitespace-only statements - #5065

Merged
herin049 merged 7 commits into
open-telemetry:mainfrom
JoeyPatricio:fix/tortoiseorm-empty-statement-indexerror
Oct 23, 2026
Merged

herin049 merged 7 commits into
open-telemetry:mainfrom
JoeyPatricio:fix/tortoiseorm-empty-statement-indexerror

Conversation

@JoeyPatricio

@JoeyPatricio JoeyPatricio commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Description

Same class as #4934 / #4936 / #4942 / #4943, in the tortoiseorm instrumentation's _do_execute. The span name is taken as the first token of the statement with an unguarded args[0].split()[0]. An empty or whitespace-only statement has no tokens, so the wrapper raises IndexError and the user's query never reaches the driver. Without the instrumentor the same call succeeds.

Guards it the same way the dbapi base does (tokens[0] if tokens else "").

Repro on main (tortoise-orm 1.1.8 and the pinned 0.20.0):

TortoiseORMInstrumentor().instrument()
await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
await Tortoise.get_connection("default").execute_query("   ")
  File ".../opentelemetry/instrumentation/tortoiseorm/__init__.py", line 268, in _do_execute
    name = args[0].split()[0]
IndexError: list index out of range

Only raw SQL passed through the execute_* client methods is affected; ORM-generated SQL is never empty.

The same line also took a leading /* ... */ comment as the operation, so /* c */ SELECT 1 produced a span named /*. It now strips the comment with the same ^/\*.*?\*/ regex dbapi, asyncpg, psycopg and sqlalchemy use. A statement that is only a comment has no tokens left and gets the fallback name. Suggested in review.

No open issue for this one; found while checking for siblings of #4934.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

Added test_span_name_empty_or_whitespace_statement. It fails on main with IndexError and passes with the fix. Added test_span_name_strips_leading_comment, which fails before the strip with span names ['CREATE', '/*', '/*']. tox -e py313-test-instrumentation-tortoiseorm (9 passed), tox -e lint-instrumentation-tortoiseorm and ruff check / ruff format --check pass.

Does This PR Require a Core Repo Change?

  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

@linux-foundation-easycla

linux-foundation-easycla Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: JoeyPatricio / name: JoeyPatricio (e77952f)

@JoeyPatricio
JoeyPatricio marked this pull request as ready for review September 15, 2026 06:38
@JoeyPatricio
JoeyPatricio requested a review from a team as a code owner September 15, 2026 06:38

@henry3260 henry3260 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall looks great just one nit

…no tokens

Fallback suggested in review.

Co-authored-by: Henry Chen <108824346+henry3260@users.noreply.github.com>

@Shriprasad-P Shriprasad-P left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Looks focused from a first pass — please confirm tests cover the new path and CI is green.

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Merged · refreshed 2026-10-23 18:44 UTC

Status above doesn't look right?
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

@JoeyPatricio

Copy link
Copy Markdown
Contributor Author

Both already in place on the current head: \test_span_name_empty_or_whitespace_statement\ exercises an empty and a whitespace-only statement and asserts each span gets the :memory:\ fallback name instead of raising, and CI is green on c72a159.

@tammy-baylis-swi tammy-baylis-swi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for another one

@tammy-baylis-swi tammy-baylis-swi moved this to Approved PRs in Python PR digest Sep 21, 2026
@tammy-baylis-swi

Copy link
Copy Markdown
Contributor

/dashboard route:reviewers

@opentelemetry-pr-dashboard

Copy link
Copy Markdown

@tammy-baylis-swi, this pull request was routed to reviewers. The handoff remains active across pushes until newer actionable human feedback arrives. Top-level feedback through this request will not return; unresolved review threads remain open.

@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

This PR has been automatically marked as stale because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 days of this comment.
If you're still working on this, please add a comment or push new commits.

@github-actions github-actions Bot added Stale and removed Stale labels Oct 6, 2026
@JoeyPatricio

Copy link
Copy Markdown
Contributor Author

Bumping this so it doesn't go stale. @xrmx, could you take a look when you have a moment?

@chrikrah chrikrah left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoeyPatricio the guard fixes the crash your body reproduces. I ran the package suite at 9c33139, then put the base __init__.py over yours and the new case died on IndexError. I would merge this as it stands.

$ cd /scratch/lane18/a_tortoise/head && CORE_REPO_SHA=9406f34 .venv-scout/bin/tox -e py312-test-instrumentation-tortoiseorm   # head 9c331395a0df120c88051e7ff7cfad192a0a0b5d, Python 3.12.3, pytest 7.4.4
instrumentation/opentelemetry-instrumentation-tortoiseorm/tests/test_tortoiseorm_instrumentation.py::TestTortoiseORMInstrumentor::test_span_name_empty_or_whitespace_statement PASSED [ 37%]
============================== 8 passed in 0.59s ===============================
py312-test-instrumentation-tortoiseorm: OK (2.84=setup[1.74]+cmd[1.10] seconds)
# CORE_REPO_SHA pins core before 0f5c340 (2026-09-25): core main then moved to 0.67b0.dev0, and contrib's
#   `opentelemetry-semantic-conventions == 0.66b0.dev` pin stops resolving against it on a fresh run
# not run: lint-instrumentation-tortoiseorm, ruff, typecheck, the other package suites
$ cp /scratch/lane18/a_tortoise/base/instrumentation/opentelemetry-instrumentation-tortoiseorm/src/opentelemetry/instrumentation/tortoiseorm/__init__.py instrumentation/opentelemetry-instrumentation-tortoiseorm/src/opentelemetry/instrumentation/tortoiseorm/__init__.py && CORE_REPO_SHA=9406f34 .venv-scout/bin/tox -e py312-test-instrumentation-tortoiseorm
FAILED instrumentation/opentelemetry-instrumentation-tortoiseorm/tests/test_tortoiseorm_instrumentation.py::TestTortoiseORMInstrumentor::test_span_name_empty_or_whitespace_statement
E       IndexError: list index out of range
instrumentation/opentelemetry-instrumentation-tortoiseorm/src/opentelemetry/instrumentation/tortoiseorm/__init__.py:268: IndexError
========================= 1 failed, 7 passed in 0.34s ==========================

non-blocking: dbapi strips a leading /* ... */ before it takes the token, and this wrapper does not, so a statement that opens with a block comment names its span /*. I would reuse that one regex here while the line is open.

$ .tox/py312-test-instrumentation-tortoiseorm/bin/python -m pytest instrumentation/opentelemetry-instrumentation-tortoiseorm/tests/test_tortoiseorm_instrumentation.py::TestTortoiseORMInstrumentor::test_probe_leading_comment_span_name -q -s   # probe method appended to the test file, removed after the run
PROBE span names: ['CREATE', '/*']
1 passed in 0.22s
$ python3 -c "import re; print(re.compile(r'^/\*.*?\*/').sub('', '/* c */ select 1).split()[0])"
select

Would you take the comment strip in this change?

A statement starting with /* ... */ produced a span named /*. Use the same regex as dbapi, asyncpg, psycopg and sqlalchemy.
@JoeyPatricio

Copy link
Copy Markdown
Contributor Author

Thanks for running it against the base. Folded the strip in with the same ^/\*.*?\*/ regex the other SQL instrumentations use. /* c */ SELECT 1 now gets SELECT, and a comment-only statement falls through to the existing :memory: fallback. Added test_span_name_strips_leading_comment, which fails before the change with ['CREATE', '/*', '/*'].

@chrikrah chrikrah left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoeyPatricio the strip went in as dbapi's own ^/\*.*?\*/, and the new test is what proves it. Put the 204b796 __init__.py back under it and the span names come out as ['CREATE', '/*', '/*']. I would merge this at 131d99a.

$ tox -e py312-test-instrumentation-tortoiseorm   # exported tree at 131d99a7b09252378f752e2bd4396904dbd5dff3, Python 3.12.3, tox 4.66.0
============================== 9 passed in 1.24s ===============================
$ git show 204b7966:instrumentation/opentelemetry-instrumentation-tortoiseorm/src/opentelemetry/instrumentation/tortoiseorm/__init__.py > instrumentation/opentelemetry-instrumentation-tortoiseorm/src/opentelemetry/instrumentation/tortoiseorm/__init__.py
$ tox -e py312-test-instrumentation-tortoiseorm   # tests from 131d99a, source from 204b796
E       AssertionError: 'SELECT' not found in ['CREATE', '/*', '/*']
========================= 1 failed, 8 passed in 0.53s ==========================
$ tox -e lint-instrumentation-tortoiseorm   # source restored to 131d99a
Your code has been rated at 10.00/10
# not run: typecheck, the other package suites

A comment-only statement now falls through to :memory:, the same fallback the empty-statement guard uses, so one branch covers both.

@emdneto, my approval carries no weight in the count here, so this needs a maintainer's. Could you review it this week?

@herin049
herin049 requested a balanced review from Copilot October 23, 2026 18:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The narrowly scoped fix addresses the reported failures with regression coverage and no identified blocking issues.

No open issues 🎉

What changed in this PR

Fixes TortoiseORM span-name parsing so empty or whitespace-only SQL reaches the driver without an instrumentation IndexError, consistent with related database instrumentation fixes.

Changes:

  • Guards empty token lists and falls back to the database name or dialect.
  • Strips a leading block comment before extracting the operation name.
  • Adds regression tests and a changelog entry.
File Description
instrumentation/​opentelemetry-instrumentation-tortoiseorm/​tests/​test_tortoiseorm_instrumentation.py Tests empty, whitespace-only, comment-prefixed, and comment-only statements.
instrumentation/​opentelemetry-instrumentation-tortoiseorm/​src/​opentelemetry/​instrumentation/​tortoiseorm/​__init__.py Guards token extraction, strips leading comments, and supplies fallback span names.
.changelog/​5065.fixed Documents the parsing fix.

Review effort: Balanced

@herin049
herin049 enabled auto-merge October 23, 2026 18:31
@herin049
herin049 added this pull request to the merge queue Oct 23, 2026
Merged via the queue into open-telemetry:main with commit f2fc9d1 Oct 23, 2026
770 checks passed
@github-project-automation github-project-automation Bot moved this from Approved PRs to Done in Python PR digest Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

7 participants