PRQL/prql · error · Error

Unexpected ` ` (this is probably a 'bad type' error)

Error message

Unexpected `{found}` (this is probably a 'bad type' error)

What it means

The lowering phase only handles expressions that the resolver has already type-checked and flattened into simple constructs. If it still encounters a `FuncCall`, `Func`, or `TransformCall`, it means a function or transform survived into lowering, which indicates a prior type error (the compiler says it is 'probably a bad type error').

Solutions

  1. Check that functions are actually called with arguments, not referenced as values
  2. Verify the argument types of your custom functions (a 'bad type' upstream likely caused this)
  3. Look for transforms (`filter`, `select`, etc.) used outside pipeline position
  4. Reformulate the expression so functions/transforms appear only in pipeline contexts

Example fix

// before
select my_func
// after
select my_func col
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure every function reference is invoked (has call args)
for (const fn of customFunctions) {
  if (!query.includes(fn.name + " ") && !query.includes(fn.name + "(")) {
    console.warn(`function ${fn.name} may be used as a value`);
  }
}

Type guard

function isCalledFunction(node) {
  return node.kind === "func_call" || node.kind === "func";
}

Try / catch

try {
  compile(query);
} catch (e) {
  if (e.message.includes("'bad type' error")) {
    console.error("Check function argument types; a function/transform leaked into value position:", e.message);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling a function in a position whose expected type does not invoke/lower it, e.g. a function used as a value `select my_func` (without call) or a transform like `filter` used as a value, or a user-defined function whose argument type inference failed.

Common situations: Forgetting to call a function (missing parentheses/arguments), passing a transform where a column is expected, or a type annotation mismatch that left the function unresolved.

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


AI-assisted analysis of PRQL/prql@e164e249b9 (2026-09-09). Data as JSON: /api/errors/af3b84dfeeac2ebb. Report an issue: GitHub.

Appendix: source

Thrown at prqlc/prqlc/src/semantic/lowering.rs:977

            pl::ExprKind::Tuple(_) => {
                return Err(
                    Error::new_simple("table instance cannot be referenced directly")
                        .push_hint("column name might be missing?")
                        .with_span(span),
                );
            }

            pl::ExprKind::Array(exprs) => rq::ExprKind::Array(
                exprs
                    .into_iter()
                    .map(|x| self.lower_expr(x))
                    .try_collect()?,
            ),

            pl::ExprKind::FuncCall(_) | pl::ExprKind::Func(_) | pl::ExprKind::TransformCall(_) => {
                log::debug!("cannot lower {expr:?}");
                return Err(Error::new(Reason::Unexpected {
                    found: format!("`{}`", write_pl(expr.clone())),
                })
                .push_hint("this is probably a 'bad type' error (we are working on that)")
                .with_span(expr.span));
            }

            pl::ExprKind::Internal(_) => {
                return Err(Error::new_assert(format!(
                    "Unresolved lowering: {}",
                    write_pl(expr)
                )))
            }
        };

        Ok(rq::Expr { kind, span })
    }

    fn lower_interpolations(

View on GitHub (pinned to e164e249b9)