risingwavelabs/risingwave · error
return type mismatch, expect
Error message
return type mismatch, expect: {:?}, actual: {:?} What it means
Same signature check as the argument mismatch, but for the return type: the return type declared in `CREATE FUNCTION` must exactly match the return type registered in the external UDF service. Mismatches abort creation of the `UdfImplDescriptor`.
Solutions
- Update the RETURNS clause in CREATE FUNCTION to match the service's return type
- Redeploy the UDF service with the return type declared in SQL
- Inspect the error's 'actual' field to see the exact service-side type
Example fix
-- before CREATE FUNCTION f(BIGINT) RETURNS INT AS 'f' USING LINK 'http://udf:8815'; -- service returns BIGINT -- after CREATE FUNCTION f(BIGINT) RETURNS BIGINT AS 'f' USING LINK 'http://udf:8815';
Defensive patterns
Strategy: validation
Validate before calling
// verify RETURNS clause matches the UDF service's return type before CREATE FUNCTION
Try / catch
try { await rw.query(createFunctionSql) } catch (e) { if (String(e).includes('return type mismatch')) { /* update RETURNS to the 'actual' type in the error */ } else throw e; } Prevention
- Keep return types stable across UDF versions
- Bump function name/version on type changes
- Read the 'actual' field of the error for the service-side type
When it happens
Trigger: `UdfImplDescriptor::new` when `data_types_match(&function.returns, &returns)` fails — the RETURNS clause in SQL differs from the UDF service's declared return type.
Common situations: UDF changed its return type (e.g. STRING to BINARY, INT to BIGINT) but the SQL DDL still has the old type; nullable/not-null mismatch between service and DDL.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- argument type mismatch, expect
- UDF returned a value of type
- UDF returned at column 0, but expected
- UDF returned at column 1, but expected
- UDF returned , but expected
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/acf4ab728aaa9a7f.
Report an issue: GitHub.
Appendix: source
Thrown at src/expr/impl/src/udf/external.rs:75
arrow_schema_udf::Field::new("row", arrow_schema_udf::DataType::Int32, true),
to_field(opts.return_type)?,
]
} else {
vec![to_field(opts.return_type)?]
});
let function = tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(client.get(&name_in_runtime))
})
.context("failed to check UDF signature")?;
if !data_types_match(&function.args, &args) {
bail!(
"argument type mismatch, expect: {:?}, actual: {:?}",
args,
function.args,
);
}
if !data_types_match(&function.returns, &returns) {
bail!(
"return type mismatch, expect: {:?}, actual: {:?}",
returns,
function.returns,
);
}
Ok(CreateFunctionOutput {
name_in_runtime,
body: None,
compressed_binary: None,
})
},
build_fn: |opts| {
let link = opts.link.context("link is required")?;
let client = get_or_create_flight_client(link)?;
Ok(Box::new(ExternalFunction {
remote_name: opts.name_in_runtime.to_owned(),
client,
disable_retry_count: AtomicU8::new(INITIAL_RETRY_COUNT),View on GitHub (pinned to 6469eb736d)