Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions sdks/python/hatchet_sdk/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from pydantic import Field, field_validator, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

from hatchet_sdk.exceptions import HatchetConfigurationError
from hatchet_sdk.token import get_addresses_from_jwt, get_tenant_id_from_jwt
from hatchet_sdk.utils.opentelemetry import OTelAttribute

Expand Down Expand Up @@ -48,15 +49,13 @@ class HealthcheckConfig(BaseSettings):
def validate_event_loop_block_threshold_seconds(
cls, value: timedelta | int | float | str
) -> timedelta:
# Settings env vars are strings; interpret as seconds.
Copy link
Contributor

Choose a reason for hiding this comment

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

let's leave this comment

if isinstance(value, timedelta):
Comment on lines 47 to 52
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

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

This hunk contains comment-only edits unrelated to token validation (the PR description says the change is intentionally scoped to token validation only). Either revert these comment-only changes here or update the PR description/scope to reflect the additional edits.

Copilot uses AI. Check for mistakes.
return value

if isinstance(value, int | float):
return timedelta(seconds=float(value))

v = value.strip()
# Allow a small convenience suffix, but keep "seconds" as the contract.
if v.endswith("s"):
v = v[:-1].strip()
Comment on lines 47 to 60
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

PR description says the change is scoped to token validation only, but this diff also removes explanatory comments in the healthcheck threshold validator. Either keep the scope strictly to token validation (revert these comment-only edits) or update the PR description to reflect the additional changes.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback


Expand Down Expand Up @@ -138,11 +137,15 @@ class ClientConfig(BaseSettings):
@model_validator(mode="after")
def validate_token_and_tenant(self) -> "ClientConfig":
if not self.token:
raise ValueError("Token must be set")
raise HatchetConfigurationError(
"HATCHET_CLIENT_TOKEN must be set. "
"Provide it via environment variable or pass token=... to ClientConfig."
)
Comment on lines 139 to +143
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

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

Token validation behavior changed (exception type/message). There are existing tests covering ClientConfig construction, but none assert the error behavior for missing/invalid tokens. Add unit tests that verify missing token and malformed token cases raise the expected configuration error (and, if required for backwards-compat, that it remains a ValueError subclass).

Copilot uses AI. Check for mistakes.

if not self.token.startswith("ey"):
raise ValueError(
f"Token must be a valid JWT. Hint: These are the first few characters of the token provided: {self.token[:5]}"
raise HatchetConfigurationError(
"HATCHET_CLIENT_TOKEN must be a valid JWT. "
f"Received token starting with: '{self.token[:5]}...'"
)
Comment on lines 137 to 149
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

In Pydantic v2 validators, raising a non-ValueError/TypeError/AssertionError exception typically bypasses normal ValidationError aggregation and will change what callers see when ClientConfig() is constructed. If the intent is to keep Pydantic-style validation errors, make HatchetConfigurationError inherit from ValueError (or use PydanticCustomError); if the intent is to surface a domain-specific exception to users, consider catching ValidationError at the ClientConfig()/Hatchet() construction boundary and rethrowing HatchetConfigurationError there so behavior is explicit and consistent.

Copilot uses AI. Check for mistakes.
Comment on lines 139 to 149
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Token validation now emits a different exception type/message, but there are no unit tests covering the missing-token and invalid-JWT paths. Add coverage in sdks/python/tests/test_client.py asserting the raised exception type (and key parts of the message) for ClientConfig(token="") and ClientConfig(token="not-a-jwt") so regressions are caught.

Copilot uses AI. Check for mistakes.

if not self.tenant_id:
Expand All @@ -152,8 +155,6 @@ def validate_token_and_tenant(self) -> "ClientConfig":

@model_validator(mode="after")
def validate_addresses(self) -> "ClientConfig":
## If nothing is set, read from the token
## If either is set, override what's in the JWT
Copy link
Contributor

Choose a reason for hiding this comment

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

let's leave these comments

server_url_from_jwt, grpc_broadcast_address_from_jwt = get_addresses_from_jwt(
self.token
)
Comment on lines 156 to 160
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

PR description notes the change is intentionally scoped to token validation only, but this diff also removes comments describing how validate_addresses derives overrides from the JWT. Either revert the comment-only edits here or adjust the PR description/scope accordingly.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Expand Down
2 changes: 2 additions & 0 deletions sdks/python/hatchet_sdk/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import traceback
from typing import cast

class HatchetConfigurationError(ValueError):
"""Raised when required configuration is missing or invalid."""

class InvalidDependencyError(Exception):
pass
Expand Down