HumanSignal / HumanSignal/label-studio
Naive datetime on OutstandingToken.expires_at triggers Django warning on GET /api/token
- Dominant language
- TypeScript
- Stars
- 28.3k
- Forks
- 3.7k
- Avg merge
- 14h
- Merged PRs (30d)
- 15
Description
### Describe the bug
While serving GET /api/token, Django warns that OutstandingToken.expires_at is given a naive datetime even though timezone support is active (USE_TZ=True). The response still returns 200, but assigning naive datetimes to DateTimeField in this mode is deprecated behavior and can cause incorrect expiry behavior depending on server timezone.
```
/label-studio/.venv/lib/python3.13/site-packages/django/db/models/fields/__init__.py:1665: RuntimeWarning: DateTimeField OutstandingToken.expires_at received a naive datetime (2026-04-30 09:42:43.759012) while time zone support is active.
warnings.warn(
```
### To Reproduce
1. Start Label Studio with the official Docker image, for example: `docker run -it -p 8080:8080 -v $(pwd)/mydata:/label-studio/data heartexlabs/label-studio:latest`
2. From a client (browser or API), trigger a request to the token endpoint, e.g. GET /api/token.
3. Check the Label Studio server/container logs at the time of the request.
4. See the RuntimeWarning above (often right before the access log line showing 200).
### Expected behavior
Token / outstanding-token persistence should use timezone-aware datetimes (e.g. `django.utils.timezone.now()` or UTC-aware values) for `expires_at`, so no warning is emitted when USE_TZ is enabled.
### Screenshots
Not applicable (warning appears in server logs, not the UI).
### Environment (please complete the following information):
- OS: macOS (Docker host); exact image as run in container.
- Label Studio Version: heartexlabs/label-studio:latest (add exact digest or output of label-studio --version inside the container if you can).
- Context from logs: Python 3.13 venv path in image; Django warning from model field assignment during /api/token.
### Additional context
OutstandingToken is typically from django-rest-framework-simplejwt (refresh/blacklist); the fix is likely ensuring expiry datetimes are created with Django’s timezone helpers, not naive datetime.now().
Access log showed: "GET /api/token HTTP/1.1" 200 200 immediately after the warning.
Contributor guide
Assessment
This issue has not been assessed yet.