diesel-rs/diesel · error · syn::Error

invalid variadic argument count: not enough function…

Error message

invalid variadic argument count: not enough function arguments

What it means

The `#[sql_function]` / `sql_function!` macro computes how many non-variadic arguments remain by subtracting the variadic argument count from the total declared arguments. If the declared argument count is smaller than the variadic count, the subtraction underflows and this error is raised in `expand_variadic`.

Solutions

  1. Ensure the total number of function arguments is greater than or equal to the variadic argument count.
  2. Reduce the `#[variadic(n)]` count to match the actual trailing arguments it should cover.
  3. Add the missing non-variadic arguments to the function signature.

Example fix

// before
#[sql_function]
#[variadic(3)]
fn concat_ws(sep: VarChar); // only 1 arg, variadic needs 3

// after
#[sql_function]
#[variadic(3)]
fn concat_ws(sep: VarChar, a: VarChar, b: VarChar, c: VarChar); // 1 + 3 args
Defensive patterns

Strategy: validation

Validate before calling

// Verify before compiling: total args must be >= variadic count
// #[variadic(N)] requires len(args) >= N
const TOTAL_ARGS: usize = 4;
const VARIADIC_COUNT: usize = 3;
assert!(TOTAL_ARGS >= VARIADIC_COUNT);

Prevention

When it happens

Trigger: Declaring a SQL function with fewer total arguments than the number given to `#[variadic(N)]` (or `last_arguments = N`), e.g. `#[variadic(3)]` on a function with only 2 arguments.

Common situations: Copy-pasting a variadic function definition and removing arguments without adjusting the variadic count; miscounting which trailing arguments the variadic covers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of diesel-rs/diesel@6fa6ed01b2 (2026-09-07). Data as JSON: /api/errors/c508e3830c52c7f6. Report an issue: GitHub.

Appendix: source

Thrown at diesel_derives/src/sql_function.rs:189

    mut input: SqlFunctionDecl,
    legacy_helper_type_and_module: bool,
    generate_return_type_helpers: bool,
    variadic_argument_count: usize,
    variant_no: usize,
    variadic_span: Span,
) -> syn::Result<ExpandedSqlFunction> {
    add_variadic_doc_comments(&mut input.attributes, &input.fn_name.to_string());

    let sql_name = parse_sql_name_attr(&mut input);

    input.fn_name = format_ident!("{}_{}", input.fn_name, variant_no);

    let nonvariadic_args_count = input
        .args
        .len()
        .checked_sub(variadic_argument_count)
        .ok_or_else(|| {
            syn::Error::new(
                variadic_span,
                "invalid variadic argument count: not enough function arguments",
            )
        })?;

    let mut variadic_generic_indexes = vec![];
    let mut arguments_with_generic_types = vec![];
    for (arg_idx, arg) in input.args.iter().skip(nonvariadic_args_count).enumerate() {
        // If argument is of type that definitely cannot be a generic then we skip it.
        let Type::Path(ty_path) = arg.ty.clone() else {
            continue;
        };
        let Ok(ty_ident) = ty_path.path.require_ident() else {
            continue;
        };

        let idx = input.generics.params.iter().position(|param| match param {
            GenericParam::Type(type_param) => type_param.ident == *ty_ident,

View on GitHub (pinned to 6fa6ed01b2)