Skip to content

fix(tool-registry): pass naive UTC datetime to fix PostgreSQL timestamp error on v1.82.0-stable - #23481

Merged
joereyna merged 1 commit into
BerriAI:litellm_stable_v1_82_0from
joereyna:fix/stable-tool-registry-timestamp
Mar 14, 2026
Merged

fix(tool-registry): pass naive UTC datetime to fix PostgreSQL timestamp error on v1.82.0-stable#23481
joereyna merged 1 commit into
BerriAI:litellm_stable_v1_82_0from
joereyna:fix/stable-tool-registry-timestamp

Conversation

@joereyna

Copy link
Copy Markdown
Contributor

Summary

Fixes continuous tool_registry_writer batch_upsert_tools error: ERROR: column "created_at" is of type timestamp without time zone but expression is of type text on v1.82.0-stable with PostgreSQL.

  • datetime.now(timezone.utc).isoformat() produces a timezone-aware string ("2026-03-12T13:34:30+00:00") that PostgreSQL rejects when binding to a timestamp without time zone column via execute_raw
  • Replace with .replace(tzinfo=None) to produce a timezone-naive UTC datetime that Prisma passes natively — no ::timestamp cast needed, no schema changes required
  • Applies to both batch_upsert_tools and update_tool_policy call sites

Impact

Reported as ~185 errors/hour on Cloud Run + Cloud SQL PostgreSQL (v1.82.0-stable). Error fires every ~8 seconds for any deployment with tool calling enabled.

Related

Test plan

  • tests/test_litellm/proxy/db/test_tool_registry_writer.py — 11/11 passing locally
  • Deploy v1.82.0-stable patch against PostgreSQL and send a chat completion with tool use
  • Confirm tool_registry_writer batch_upsert_tools error no longer appears in logs

…mp type error

`datetime.now(timezone.utc).isoformat()` produces a timezone-aware string
("2026-03-12T13:34:30+00:00") that PostgreSQL rejects when binding to a
`timestamp without time zone` column via execute_raw, logging:

  ERROR: column "created_at" is of type timestamp without time zone
  but expression is of type text

Replacing with `.replace(tzinfo=None)` produces a timezone-naive UTC datetime
that Prisma passes natively without needing ::timestamp casts. The stored
value is correct because the source is always UTC.

Fixes the ~185 errors/hour reported against v1.82.0-stable with PostgreSQL.
Applies to both batch_upsert_tools and update_tool_policy call sites.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Mar 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Error Error Mar 12, 2026 9:04pm

Request Review

@greptile-apps

greptile-apps Bot commented Mar 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This is a minimal, targeted fix for a PostgreSQL type-binding error in litellm/proxy/db/tool_registry_writer.py on the litellm_stable_v1_82_0 branch. The root cause was that datetime.now(timezone.utc).isoformat() produces a timezone-aware ISO 8601 string (e.g. "2026-03-12T13:34:30+00:00"), which PostgreSQL rejects when Prisma binds it to a timestamp without time zone column via execute_raw. Replacing it with .replace(tzinfo=None) produces a naive datetime object that Prisma serialises correctly for that column type.

Key points:

  • Fix is applied consistently to both batch_upsert_tools (line 65) and update_tool_policy (line 143).
  • No schema changes, no new dependencies — a 2-line surgical patch.
  • The fix deliberately avoids datetime.utcnow() (deprecated in Python 3.12+), choosing the modern idiom datetime.now(timezone.utc).replace(tzinfo=None) instead.
  • A minor pre-existing observation (not introduced by this PR): now is instantiated inside the for loop in batch_upsert_tools, so each row in a batch receives a marginally different created_at/updated_at timestamp. This could be pulled above the loop for consistency, but it does not affect correctness.
  • The PR description references 11/11 unit tests passing, but the test file (tests/test_litellm/proxy/db/test_tool_registry_writer.py) is not part of the diff — only pre-existing or separately-run tests are verified, and a live PostgreSQL smoke test is still marked as TODO.

Confidence Score: 4/5

  • Safe to merge for the stable branch — two-line change with a correct fix, though a live PostgreSQL smoke test is still pending.
  • The change is semantically correct: datetime.now(timezone.utc).replace(tzinfo=None) produces a naive UTC datetime that Prisma's execute_raw can bind cleanly to a timestamp without time zone column. No regressions are introduced for SQLite deployments since Prisma handles naive datetime serialisation for both backends. Score is 4 rather than 5 only because the PR's own test plan marks the PostgreSQL smoke-test as unchecked, leaving a small gap in end-to-end verification.
  • No files require special attention.

Important Files Changed

Filename Overview
litellm/proxy/db/tool_registry_writer.py Two call sites changed from .isoformat() (returning a timezone-aware string) to .replace(tzinfo=None) (returning a naive datetime object). Fix is correct and consistent; minor pre-existing issue of now being created inside the loop is unrelated to this PR.

Sequence Diagram

sequenceDiagram
    participant LLM as LLM Response
    participant TRW as tool_registry_writer
    participant Prisma as Prisma Client
    participant PG as PostgreSQL

    LLM->>TRW: discovered tool names
    TRW->>TRW: now = datetime.now(UTC).replace(tzinfo=None)<br/>(naive UTC datetime)
    TRW->>Prisma: execute_raw(INSERT ... $8=now, ...)
    Prisma->>PG: bind now → timestamp without time zone ✅
    PG-->>Prisma: OK / conflict → increment call_count
    Prisma-->>TRW: success
    TRW-->>LLM: upserted

    note over TRW,PG: Previously: .isoformat() produced "2026-03-12T13:34:30+00:00"<br/>→ PostgreSQL rejected text → timestamp cast ❌
Loading

Last reviewed commit: a73b1ca

@joereyna
joereyna merged commit 8eb2daf into BerriAI:litellm_stable_v1_82_0 Mar 14, 2026
4 of 5 checks passed
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.

1 participant