diff --git a/federation-2/router-bridge/js-src/plan_worker.ts b/federation-2/router-bridge/js-src/plan_worker.ts index 4c2c2b20b..75cecf168 100644 --- a/federation-2/router-bridge/js-src/plan_worker.ts +++ b/federation-2/router-bridge/js-src/plan_worker.ts @@ -305,7 +305,7 @@ async function run() { extensions: { code: "QUERY_PLANNING_FAILED", exception: { - stacktrace: e.toString().split(/\n/), + stacktrace: e.toString(), }, }, }; @@ -330,7 +330,7 @@ async function run() { extensions: { code: "QUERY_PLANNING_FAILED", exception: { - stacktrace: e.toString().split(/\n/), + stacktrace: e.toString(), }, }, }; diff --git a/federation-2/router-bridge/src/planner.rs b/federation-2/router-bridge/src/planner.rs index dab25f68c..703ad0434 100644 --- a/federation-2/router-bridge/src/planner.rs +++ b/federation-2/router-bridge/src/planner.rs @@ -2216,4 +2216,89 @@ feature https://specs.apollo.dev/unsupported-feature/v0.1 is for: SECURITY but i .data .unwrap()).unwrap()); } + + #[tokio::test] + async fn propagate_internal_qp_errors() { + let schema = r#" + schema + @link(url: "https://specs.apollo.dev/link/v1.0") + @link(url: "https://specs.apollo.dev/join/v0.2", for: EXECUTION) + { + query: Query + subscription: Subscription + } + + directive @join__field(graph: join__Graph!, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION + directive @join__graph(name: String!, url: String!) on ENUM_VALUE + directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE + directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR + directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA + + scalar link__Import + enum link__Purpose { + SECURITY + EXECUTION + } + + type Computer + @join__type(graph: COMPUTERS) + { + id: ID! + errorField: String + nonNullErrorField: String! + gpus: [GPU] + } + + type GPU @join__type(graph: COMPUTERS) @join__type(graph: GPUS) { + id: ID! + wattage: Int! @join__field(graph: GPUS) + } + + scalar join__FieldSet + + enum join__Graph { + COMPUTERS @join__graph(name: "computers", url: "http://localhost:4001/") + GPUS @join__graph(name: "gpus", url: "http://localhost:4002/") + } + + + type Query + @join__type(graph: COMPUTERS) + { + computer(id: ID!): Computer + } + type Subscription @join__type(graph: COMPUTERS) { + computer(id: ID!): Computer + }"#; + + let planner = Planner::::new( + schema.to_string(), + QueryPlannerConfig { + incremental_delivery: Some(IncrementalDeliverySupport { + enable_defer: Some(true), + }), + graphql_validation: true, + reuse_query_fragments: None, + generate_query_fragments: None, + debug: Default::default(), + }, + ) + .await + .unwrap(); + + insta::assert_snapshot!(serde_json::to_string_pretty( + &planner + .plan( + "subscription { computer(id: 1) { ... @defer { gpus { wattage } } } }" + .to_string(), + None, + PlanOptions::default(), + ) + .await + .unwrap() + .errors + .unwrap() + ) + .unwrap()); + } } diff --git a/federation-2/router-bridge/src/snapshots/router_bridge__planner__error_display__propagate_internal_qp_errors.snap b/federation-2/router-bridge/src/snapshots/router_bridge__planner__error_display__propagate_internal_qp_errors.snap new file mode 100644 index 000000000..6d18432ca --- /dev/null +++ b/federation-2/router-bridge/src/snapshots/router_bridge__planner__error_display__propagate_internal_qp_errors.snap @@ -0,0 +1,15 @@ +--- +source: router-bridge/src/planner.rs +expression: "serde_json::to_string_pretty(&planner.plan(\"subscription { computer(id: 1) { ... @defer { gpus { wattage } } } }\".to_string(),\n None,\n PlanOptions::default()).await.unwrap().errors.unwrap()).unwrap()" +--- +[ + { + "message": "@defer is not supported on subscriptions", + "extensions": { + "code": "QUERY_PLANNING_FAILED", + "exception": { + "stacktrace": "Error: @defer is not supported on subscriptions" + } + } + } +]