Skip to content

fix(server): annotate SQLAlchemy result rows for 2.1 type inference [SAO-17580] - #272

Merged
josjeon merged 1 commit into
mainfrom
fix-sqlalchemy-21-typecheck
Sep 28, 2026
Merged

josjeon merged 1 commit into
mainfrom
fix-sqlalchemy-21-typecheck

Conversation

@josjeon

@josjeon josjeon commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

make typecheck currently fails on main and on every open PR. This annotates the four call sites that SQLAlchemy 2.1.0 broke, unblocking merges.

The failure belongs to no branch's changes.

What happened

SQLAlchemy 2.1.0 no longer lets mypy infer the element type through result.scalars().all():

server/src/agent_control_server/services/control_bindings.py:282:
  error: Need type annotation for "rows" (hint: "rows: list[<type>] = ...")  [var-annotated]
Found 1 error in 1 file (checked 51 source files)
make: *** [Makefile:138: typecheck] Error 1

The repository lock pins 2.0.51, which still infers it, so the error appears only in CI, where dependencies resolve fresh. Main's own run at bd7d91f installs both and reports the error in the same log:

+ mypy==2.3.1
+ sqlalchemy==2.1.0
server/src/agent_control_server/services/control_bindings.py:282: error: Need type annotation for "rows"

Evidence this is not branch-specific

Branch Date CI
main 2026-09-22 success
main 2026-09-24 failure
fix/sao-17418-runtime-token-auth 2026-09-24 success
fix/sao-17418-runtime-token-auth 2026-09-28 failure

SQLAlchemy 2.1.0 was released between those dates, and the flagged file is not in the diff of either affected PR. Re-running the job does not clear it: CI resolves 2.1.0 again each time, so the failure is deterministic rather than flaky.

What changed

Four sites share the pattern. CI reports only the first, so fixing them one at a time would surface the next on the following run.

File Annotation
services/control_bindings.py:282 rows: list[ControlBinding]
services/controls.py:306 versions: list[ControlVersion]
services/controls.py:512 controls: list[Control]
endpoints/agents.py:463 agents: Sequence[Agent]

agents.py keeps Sequence rather than list because that call site does not wrap the result in list() and only reads and slices it. Sequence and Agent were already imported there.

Scope

  • Type annotations only. No runtime behavior changes, no control flow, no queries touched.
  • Deliberately out of scope: raising the SQLAlchemy floor in pyproject.toml or regenerating the lock. That is a wider dependency decision, and these annotations are correct under either version.

Risk and Rollout

  • Risk level: minimal. Annotations are erased at runtime.
  • No migration or configuration change.
  • Rollback plan: revert this PR.

Testing

  • mypy server/src clean under the locked versions: 51 source files, no issues.
  • ruff check server/src clean.
  • Full server test suite: not run locally. The local Docker daemon is unresponsive, so the Postgres-backed suite cannot start. CI covers it here, and the change is annotations only.
  • Reproduced the failure locally against CI's resolved versions: not possible right now, the internal package index returns 401. The CI log for main is cited above instead.

Checklist

AI Tool Assistance Usage Statement

  • AI assistance was used to draft parts of the implementation, that was subsequently modified and extended.
  • AI assistance was used in generating tests/documentation/comments for this change.
  • AI assistance was used for optimizing/troubleshooting/refactoring existing code in this change.
  • AI assistance was used to draft this entire change as is.

…SAO-17580]

SQLAlchemy 2.1.0 no longer lets mypy infer the element type through
`result.scalars().all()`, so `make typecheck` fails on `main` and on every open
PR with var-annotated. The repository lock pins 2.0.51, which still infers it,
so the error surfaces only in CI where dependencies resolve fresh. Main's own
run at bd7d91f installs mypy 2.3.1 and sqlalchemy 2.1.0 and reports the error,
which is why re-running a job does not clear it.

Annotate all four call sites that share the pattern. CI reports only the first,
so fixing them one at a time would surface the next on the following run. The
annotations hold under 2.0.51 and 2.1.0 alike, so the result does not depend on
which version CI resolves.

Raising the SQLAlchemy floor or regenerating the lock is left alone. That is a
wider dependency decision, and these annotations are correct either way.
@codecov

codecov Bot commented Sep 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@josjeon
josjeon enabled auto-merge (squash) September 28, 2026 19:45
@josjeon
josjeon merged commit ad6a257 into main Sep 28, 2026
6 checks passed
@josjeon
josjeon deleted the fix-sqlalchemy-21-typecheck branch September 28, 2026 19:52
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.

2 participants