windmill-labs/windmill · error

Missing otyp for pg arg

Error message

Missing otyp for pg arg

What it means

The PostgreSQL executor builds typed query parameters from the script's argument definitions; each arg needs an `otyp` (the resolved PostgreSQL OID/type name) to convert the JSON value into a typed parameter. When an argument has no `otyp`, conversion cannot proceed and this error aborts the query preparation.

Source

Thrown at backend/windmill-worker/src/pg_executor.rs:486

    let mut default_values: HashMap<i32, serde_json::Value> = HashMap::new();

    for oidx in arg_indices.iter().sorted() {
        if let Some((arg, value)) = param_idx_to_arg_and_value.get(&oidx) {
            // Resolve the value: explicit user value > declaration default > NULL.
            let value: &serde_json::Value = match (value, arg.default.as_ref()) {
                (Some(v), _) => *v,
                (None, Some(d)) => default_values.entry(*oidx).or_insert_with(|| d.clone()),
                (None, None) => {
                    if !arg.has_default && !missing_args.contains(&arg.name) {
                        missing_args.push(arg.name.clone());
                    }
                    &serde_json::Value::Null
                }
            };
            let arg_t = arg
                .otyp
                .as_ref()
                .ok_or_else(|| anyhow::anyhow!("Missing otyp for pg arg"))?;
            let typ = &arg.typ;
            let (param, natural_type) = convert_val(value, arg_t, typ, arg.otyp_inferred)?;
            query_params.push(param);
            param_meta.push((arg.name.clone(), json_value_kind(value)));
            if all_types_resolved {
                if otyp_to_pg_type(arg_t).is_ok() {
                    // The Type comes from convert_val (paired with the binding's
                    // concrete Rust type) rather than from `otyp_to_pg_type(arg_t)`
                    // — this prevents the parser-default "text" otyp from
                    // forcing an assertion that the encoder can't satisfy
                    // (e.g. Value::Bool with parser-defaulted text → Type::TEXT
                    // on a Box<bool>).
                    param_types.push(natural_type);
                } else {
                    all_types_resolved = false;
                    param_types.clear();
                }
            }

View on GitHub (pinned to e474e8803c)

Solutions

  1. Open the script's argument definition and set an explicit type for the offending argument so `otyp` resolves.
  2. Check the arg name in the error path against the script's args; fix missing/renamed parameters in the code and args list.
  3. If the type is unusual (custom enum, domain), cast it in SQL (`$1::my_type`) or use a supported base type instead.
  4. Re-save the script through the UI so args are re-validated and otyp is populated; retry the job.

Example fix

// before: arg declared without type in script args
// { "name": "limit", "value": 10 }  // no type -> otyp None
// after
// { "name": "limit", "value": 10, "type": "integer" }
Defensive patterns

Strategy: validation

Validate before calling

// validate args carry a type before executing the script
for arg in args {
    if arg.otyp.is_none() {
        return Err(format!("argument '{}' has no resolved type; declare it in the script args", arg.name));
    }
}

Type guard

fn has_resolved_type(arg: &PgArg) -> bool {
    arg.otyp.as_ref().map(|t| !t.is_empty()).unwrap_or(false)
}

Prevention

When it happens

Trigger: `do_postgresql_inner` processing args where `arg.otyp` is `None` — the type was never resolved for the parameter (e.g. argument defined without a type in the script UI/resource, or type inference failed and `otyp_inferred` didn't fill it in).

Common situations: Script args edited via the API/CLI omitting the type field; a Postgres type not recognized by Windmill so resolution was skipped; older scripts whose stored args lack otyp after an executor change; passing a null/complex JSON value with no declared parameter type.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/c11bcc99972ac87b. Report an issue: GitHub.