Skip to content

Commit cf40c80

Browse files
dowskiConvex, Inc.
authored andcommitted
Handle Node arguments that are too large for a local backend (#41613)
Previously this wasn't handled and caused a WebSocket disconnect. Now it will return the same error message that is returned when using the cloud version of Convex. GitOrigin-RevId: 1fa099fe5fc18199bcc5797ac11b24e9935843f7
1 parent 150cbb8 commit cf40c80

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

crates/node_executor/src/executor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ pub static EXECUTE_TIMEOUT_RESPONSE_JSON: LazyLock<JsonValue> = LazyLock::new(||
126126
)
127127
});
128128

129+
pub const ARGS_TOO_LARGE_RESPONSE_MESSAGE: &str =
130+
"Node actions arguments size is too large. The maximum size is 5 MiB. Reduce the size of the \
131+
arguments or consider using V8 actions instead, which have a 16 MiB limit.";
132+
129133
const NODE_ANALYZE_INITIAL_BACKOFF: Duration = Duration::from_millis(100);
130134
const NODE_ANALYZE_MAX_BACKOFF: Duration = Duration::from_secs(5);
131135

crates/node_executor/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ pub use crate::executor::{
3030
Package,
3131
ResponsePart,
3232
SourcePackage,
33+
ARGS_TOO_LARGE_RESPONSE_MESSAGE,
3334
EXECUTE_TIMEOUT_RESPONSE_JSON,
3435
};

crates/node_executor/src/local.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::{
3131
ExecutorRequest,
3232
InvokeResponse,
3333
NodeExecutor,
34+
ARGS_TOO_LARGE_RESPONSE_MESSAGE,
3435
EXECUTE_TIMEOUT_RESPONSE_JSON,
3536
},
3637
handle_node_executor_stream,
@@ -252,7 +253,15 @@ impl NodeExecutor for LocalNodeExecutor {
252253
},
253254
};
254255

255-
if !response.status().is_success() {
256+
if let Err(e) = response.error_for_status_ref() {
257+
if e.status() == Some(reqwest::StatusCode::PAYLOAD_TOO_LARGE) {
258+
return Err(
259+
anyhow::anyhow!(e.without_url()).context(ErrorMetadata::bad_request(
260+
"ArgsTooLarge",
261+
ARGS_TOO_LARGE_RESPONSE_MESSAGE,
262+
)),
263+
);
264+
}
256265
let error = response.text().await?;
257266
anyhow::bail!("Node executor server returned error: {}", error);
258267
}
@@ -301,7 +310,10 @@ mod tests {
301310
value::ConvexValue,
302311
version::Version,
303312
};
304-
use errors::ErrorMetadataAnyhowExt;
313+
use errors::{
314+
ErrorMetadata,
315+
ErrorMetadataAnyhowExt,
316+
};
305317
use futures::FutureExt;
306318
use isolate::test_helpers::TEST_SOURCE;
307319
use keybroker::{
@@ -650,6 +662,40 @@ mod tests {
650662
Ok(())
651663
}
652664

665+
#[convex_macro::prod_rt_test]
666+
async fn test_args_too_large(rt: ProdRuntime) -> anyhow::Result<()> {
667+
let storage = Arc::new(LocalDirStorage::new(rt.clone())?);
668+
let actions = create_actions(rt).await;
669+
let source_package = upload_modules(storage.clone(), TEST_SOURCE.clone()).await?;
670+
671+
// Create ~6MB of args data, which is too large for Node functions.
672+
let args = create_args(assert_obj!(
673+
"message" => "a".repeat(6 * 1024 * 1024)
674+
))?;
675+
let path_and_args = ValidatedPathAndArgs::new_for_tests(
676+
"node_actions.js:echoMessage".parse()?,
677+
args,
678+
VERSION.clone(),
679+
);
680+
let error = execute(
681+
&actions,
682+
execute_request(path_and_args, source_package),
683+
empty_source_maps_callback(),
684+
)
685+
.await
686+
.unwrap_err();
687+
688+
assert_eq!(
689+
&error.to_string(),
690+
"Node actions arguments size is too large. The maximum size is 5 MiB. Reduce the size \
691+
of the arguments or consider using V8 actions instead, which have a 16 MiB limit."
692+
);
693+
let metadata = error.downcast_ref::<ErrorMetadata>().unwrap();
694+
assert!(metadata.is_deterministic_user_error());
695+
696+
Ok(())
697+
}
698+
653699
#[convex_macro::prod_rt_test]
654700
async fn test_forgot_await(rt: ProdRuntime) -> anyhow::Result<()> {
655701
let storage = Arc::new(LocalDirStorage::new(rt.clone())?);

npm-packages/udf-tests/convex/node_actions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,9 @@ export const actionCallsAction = actionGeneric(
104104
export const partialEscapeSequence = actionGeneric(async () => {
105105
return "\ud83c...";
106106
});
107+
108+
export const echoMessage = actionGeneric(
109+
async (_, { message }: { message: string }) => {
110+
return message;
111+
},
112+
);

0 commit comments

Comments
 (0)