Skip to content

Commit 5f4252b

Browse files
authored
fix(router): better handling of internal and pipeline errors (#1387)
1 parent 9d955ef commit 5f4252b

26 files changed

Lines changed: 615 additions & 282 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
hive-router-plan-executor: patch
3+
hive-router: patch
4+
---
5+
6+
# Improve variable coercion error messages
7+
8+
Variable coercion errors (invalid scalar/enum/object values, missing required fields, non-null violations) reports clear and informative error messages.
9+
10+
This only changes error text - error codes and HTTP status codes are unchanged.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
hive-router: patch
3+
---
4+
5+
# Mask internal error details from client responses
6+
7+
Improve router's error handling by masking internal error details from client responses.
8+
9+
Client-caused errors still return their real message, since it only ever reflects the client's own request. Internal errors now always return a generic `"Internal server error"` message and never the underlying error message, which previously leaked details such as subgraph URLs, storage/network errors, and other backend internals. The real error is still logged for debugging purposes.
10+
11+
Error codes are unchanged. HTTP status codes are unchanged, except for GraphQL operation normalization and minification failures, which are now correctly treated as router-side bugs and always return `500` (previously `400`, or `200` based on `Accept` header) instead of being treated as a client mistake.

bin/router/src/pipeline/authorization/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub mod metadata;
1212

1313
use std::sync::Arc;
1414

15-
use crate::pipeline::error::PipelineError;
15+
use crate::pipeline::error::{ClientPipelineError, PipelineError};
1616
use crate::pipeline::normalize::GraphQLNormalizationPayload;
1717
use crate::pipeline::nullify::rebuilder::{
1818
rebuild_nulled_operation, rebuild_nulled_projection_plan,
@@ -195,7 +195,7 @@ pub fn enforce_operation_authorization(
195195
errors,
196196
),
197197
AuthorizationDecision::Reject { errors } => {
198-
return Err(PipelineError::AuthorizationFailed(errors));
198+
return Err(ClientPipelineError::AuthorizationFailed(errors).into());
199199
}
200200
})
201201
}

bin/router/src/pipeline/coerce_variables.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hive_router_plan_executor::variables::collect_variables;
88
use sonic_rs::Value;
99
use tracing::{debug, warn};
1010

11-
use crate::pipeline::error::PipelineError;
11+
use crate::pipeline::error::{ClientPipelineError, PipelineError};
1212
use crate::pipeline::normalize::GraphQLNormalizationPayload;
1313

1414
#[inline]
@@ -35,13 +35,13 @@ pub fn coerce_request_variables(
3535
variables_map: values,
3636
})
3737
}
38-
Err(err_msg) => {
38+
Err(err) => {
3939
warn!(
4040
target: targets::COERCE_VARIABLES,
41-
error = ?err_msg,
41+
error = %err,
4242
"failed to collect variables from incoming request",
4343
);
44-
Err(PipelineError::VariablesCoercionError(err_msg))
44+
Err(ClientPipelineError::VariablesCoercionError(err).into())
4545
}
4646
}
4747
}

bin/router/src/pipeline/csrf_prevention.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use hive_router_internal::telemetry::logging::targets;
33
use ntex::web::HttpRequest;
44
use tracing::warn;
55

6-
use crate::pipeline::error::PipelineError;
6+
use crate::pipeline::error::{ClientPipelineError, PipelineError};
77

88
// NON_PREFLIGHTED_CONTENT_TYPES are content types that do not require a preflight
99
// OPTIONS request. These are content types that are considered "simple" by the CORS
@@ -43,7 +43,7 @@ pub fn perform_csrf_prevention(
4343
} else {
4444
warn!(target: targets::HTTP_SERVER, "csrf failed: missing required header");
4545

46-
Err(PipelineError::CsrfPreventionFailed)
46+
Err(ClientPipelineError::CsrfPreventionFailed.into())
4747
}
4848
}
4949

bin/router/src/pipeline/demand_control/formula.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use tracing::warn;
2121

2222
use std::{collections::BTreeMap, fmt, sync::Arc};
2323

24-
use crate::pipeline::error::PipelineError;
24+
use crate::pipeline::error::{ClientPipelineError, PipelineError};
2525

2626
/// Size overrides threaded from a parent @listSize(sizedFields:[…]) down to children.
2727
/// Each entry is (remaining path from the current selection, size expression).
@@ -305,10 +305,11 @@ fn eval_cost_expr(
305305
"rejecting operation: expected exactly one slicing argument for @listSize"
306306
);
307307

308-
Err(PipelineError::CostInvalidSlicingArguments {
308+
Err(ClientPipelineError::CostInvalidSlicingArguments {
309309
field_name: field_name.clone(),
310310
found: resolved_count,
311-
})
311+
}
312+
.into())
312313
}
313314
} else {
314315
let mut max_value: Option<u64> = None;

bin/router/src/pipeline/demand_control/runtime.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use http::{HeaderName, HeaderValue};
2525
use moka::future::Cache;
2626
use tracing::{debug, info, warn};
2727

28-
use crate::pipeline::error::PipelineError;
28+
use crate::pipeline::error::{ClientPipelineError, PipelineError};
2929

3030
use super::formula::{
3131
compile_cost_expr_for_operation, evaluate_formula_plan, DemandControlFormulaPlan,
@@ -163,9 +163,10 @@ impl DemandControlRuntime {
163163
.push((header_name.get_header_ref().to_owned(), max_cost.into()));
164164
}
165165

166-
return Err(PipelineError::CostEstimatedTooExpensive {
166+
return Err(ClientPipelineError::CostEstimatedTooExpensive {
167167
response_headers: err_extra_headers,
168-
});
168+
}
169+
.into());
169170
}
170171
DemandControlMode::Measure => {
171172
warn!(

0 commit comments

Comments
 (0)