PRQL/prql · error · Error

`by`: expected position or name, found

Error message

`by`: expected position or name, found {ident}

What it means

This error comes from PRQL's `append` transform when used with the `by` option (e.g. `append other by:...`). The `by` argument must be exactly `position` or `name`; the resolver found some other identifier instead. It is thrown because PRQL's union-all-by-name/positional implementation only supports these two explicit modes.

Solutions

  1. Change the `by:` value to exactly `position` or `name` (lowercase).
  2. If you intended to match on a column, use `by:name` after ensuring both inputs have identically named columns (e.g. add a `select` to align column names).
  3. Check the PRQL version/docs: `append by:` only accepts these two keywords; positional matching is the default via plain `append other`.

Example fix

// before
from t | append other by:colname
// after
from t | append other by:name
Defensive patterns

Strategy: validation

Validate before calling

// PRQL source check before compiling
const BY_KEYWORDS = new Set(["position", "name"]);
function validateAppendBy(prql) {
  const m = prql.match(/by:\s*([\w"]+)/);
  if (m && !BY_KEYWORDS.has(m[1].replaceAll('"', ''))) {
    throw new Error(`append by: must be 'position' or 'name', got: ${m[1]}`);
  }
}

Type guard

function isValidByKeyword(v) {
  return v === 'position' || v === 'name';
}

Try / catch

try {
  const sql = prqlc.compile(query);
} catch (e) {
  if (e.message.includes('`by`: expected position or name')) {
    // surface a fix hint: use by:position or by:name
  } else throw e;
}

Prevention

When it happens

Trigger: Compiling a PRQL query like `from t | append other by:foo` where the identifier passed to `by:` is anything other than `position` or `name` (e.g. a misspelling like `by:name ` with an ident such as `by:Name`, `by:pos`, or a column name).

Common situations: Typo in `by:position`/`by:name`; passing a column name expecting `by:` to take a column; copying SQL `UNION ... BY NAME` syntax into PRQL without adapting it; confusion from older or newer PRQL syntax examples.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at prqlc/prqlc/src/semantic/resolver/transforms.rs:253

                };
                (transform_kind, tbl)
            }
            "append" => {
                let [by, bottom, top] = unpack::<3>(func.args);

                let by_name = {
                    let span = by.span;
                    let ident = by.clone().try_cast(
                        ExprKind::into_literal,
                        Some("`by`"),
                        "position or name",
                    )?;

                    match ident.to_string().as_str() {
                        "\"position\"" => false,
                        "\"name\"" => true,
                        _ => {
                            return Err(Error::new(Reason::Expected {
                                who: Some("`by`".to_string()),
                                expected: "position or name".to_string(),
                                found: ident.to_string(),
                            })
                            .with_span(span))
                        }
                    }
                };

                // TODO: support database engine-level UNION ALL BY NAME in PR #6037
                if by_name {
                    // input validation for PRQL-native implementation
                    for (name, rel) in [("top", top.clone()), ("bottom", bottom.clone())] {
                        let lineage = rel.lineage.clone().ok_or_else(|| {
                            Error::new(Reason::Expected {
                                who: Some(format!("`{name}`")),
                                expected: "relation".to_string(),
                                found: write_pl(rel.clone()),

View on GitHub (pinned to e164e249b9)