Errors
Everything the client raises derives from MetranaQueryError, so one except covers the API:
from metrana.query import MetranaQueryError
try: frame = client.fetch_float_series(runs, "loss")except MetranaQueryError as err: ...The types
Section titled “The types”| Exception | Raised when |
|---|---|
ConfigError |
Bad client-side configuration — no workspace, no project where one is needed, a malformed endpoint URL, an unreadable CA bundle. |
TransportError |
Connection-level failure (DNS, TLS, refused) with retries exhausted — including at construction, when the endpoint is unreachable. |
RpcError |
The server answered with a non-OK gRPC status after retries for transient codes. The message carries the status code and detail. |
QueryTypeError |
An argument of the wrong type, or a builder used in a context that does not accept it. |
QueryValueError |
An argument of the right type but an unusable value — an unknown enum spelling, an out-of-range bound, a selector the endpoint cannot express. |
Every public method documents which of these it can raise, so help(client.fetch_runs) is authoritative for
that method.
The two argument errors are also builtins
Section titled “The two argument errors are also builtins”QueryTypeError derives from TypeError, and QueryValueError from ValueError:
try: client.fetch_float_series_buckets(runs, "loss", x_mode="sideways")except ValueError as err: print(err)# unknown x_mode 'sideways'; expected one of step/absolute_time/relative_timeSo ordinary handlers keep working, and an enum coercion that would have raised a bare ValueError stays
catchable the same way — while except MetranaQueryError still catches everything the SDK throws.
What is an error and what is empty
Section titled “What is an error and what is empty”Some limits are deliberately errors rather than quiet truncation, because a silently short answer is the harder bug:
client.fetch_float_series(two_thousand_runs, "loss")# QueryValueError: 2000 runs exceeds the 1000 a series fetch reads at once;# narrow the run filter or set max_runsA chart missing 1000 of its runs looks like a result. So the cap raises, and max_runs= is how you opt into a
deliberate top-N.
An empty DataFrame, by contrast, is a legitimate answer: the filter matched nothing, or the series has no
points in the range. Check frame.empty rather than catching.
Retries
Section titled “Retries”Transient gRPC statuses are retried inside the client before any exception reaches you, so RpcError and
TransportError mean the failure survived those retries. There is nothing to be gained by wrapping calls
in your own immediate retry loop; treat them as real failures.