Skip to main content

systemprompt_models/services/gateway/
error.rs

1//! Failure modes emitted while validating the gateway's references into the
2//! provider registry: duplicate route ids, and a route or `default_provider`
3//! naming a provider absent from the services provider registry.
4//!
5//! Copyright (c) systemprompt.io — Business Source License 1.1.
6//! See <https://systemprompt.io> for licensing details.
7
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11pub enum GatewayProfileError {
12    #[error("gateway route id '{id}' is declared more than once")]
13    DuplicateRouteId { id: String },
14
15    #[error("gateway route '{route}' provider '{provider}' is not declared in services providers")]
16    RouteProviderNotInRegistry { route: String, provider: String },
17
18    #[error("gateway default_provider '{provider}' is not declared in services providers")]
19    DefaultProviderNotInRegistry { provider: String },
20
21    #[error(
22        "gateway route '{route}' fallback_provider '{provider}' is not declared in services \
23         providers"
24    )]
25    RouteFallbackProviderNotInRegistry { route: String, provider: String },
26
27    #[error(
28        "gateway route '{route}' names '{provider}' as both provider and fallback_provider; a \
29         fallback must be a different upstream"
30    )]
31    RouteFallbackIsPrimary { route: String, provider: String },
32
33    #[error(
34        "gateway route '{route}' sets fallback_upstream_model without a fallback_provider to \
35         apply it to"
36    )]
37    RouteFallbackModelWithoutProvider { route: String },
38
39    #[error("system_prompt override with action 'replace' must set a 'prompt'")]
40    OverrideReplaceMissingPrompt,
41
42    #[error("system_prompt override with action 'strip' must not set a 'prompt'")]
43    OverrideStripWithPrompt,
44
45    #[error("system_prompt override provider '{provider}' is not declared in services providers")]
46    OverrideProviderNotInRegistry { provider: String },
47
48    #[error("route `when.min_tools` must be at least 1 (0 matches every request)")]
49    RouteMatchZeroMinTools,
50
51    #[error("route `when` sets `requires_tools: false` but also a positive `min_tools`")]
52    RouteMatchContradictoryTools,
53
54    #[error(
55        "gateway route '{route}' (model_pattern '{pattern}') reaches no priced model: provider \
56         '{provider}' declares no model matching the pattern and the route sets no `pricing:` \
57         override, so every request it dispatches would be billed at zero"
58    )]
59    RouteReachesNoPricedModel {
60        route: String,
61        pattern: String,
62        provider: String,
63    },
64
65    #[error(
66        "gateway route '{route}' requires [{requirements}] but can dispatch model '{model}', \
67         whose provider/model governance does not declare them — annotate the provider or model \
68         with `governance:` or drop the route requirement"
69    )]
70    RouteGovernanceUnsatisfied {
71        route: String,
72        model: String,
73        requirements: String,
74    },
75
76    #[error(
77        "gateway route '{route}' can dispatch model '{model}', which has no usable `pricing:` \
78         (input_per_million and output_per_million must both be non-zero, or per_image_cents set)"
79    )]
80    RouteModelUnpriced { route: String, model: String },
81
82    #[error(
83        "gateway route '{route}' can dispatch provider '{provider}' model '{model}', \
84         which declares no `cache_read_per_million`; every wire we speak can report cached \
85         prompt tokens, and `input_tokens` excludes them, so an absent rate bills the cached \
86         slice at zero -- set the provider's published rate, or an explicit 0.0 if it bills \
87         none"
88    )]
89    RouteModelCacheRateUndeclared {
90        route: String,
91        provider: String,
92        model: String,
93    },
94}
95
96pub type GatewayResult<T> = Result<T, GatewayProfileError>;