PRQL/prql · error · Error

std.from_text: expected a string literal, found

Error message

std.from_text: expected a string literal, found `{found}`

What it means

`std.from_text` parses inline text (CSV/JSON) into a table at compile time, so its text argument must be a literal string known during compilation. If the second argument is not a `Literal::String` (e.g. a variable, column reference, or computed expression), the resolver cannot parse it and throws this error.

Solutions

  1. Pass the text as a quoted literal string: `from_text format:"csv" text:"a,b\n1,2"`.
  2. If the data is in a table/column already, don't use `from_text` — query it directly.
  3. If the string must be dynamic, compute it outside PRQL or embed it as a literal in generated PRQL.

Example fix

// before
from_text format:"csv" text: csv_data
// after
from_text format:"csv" text:"id,name\n1,alice"
Defensive patterns

Strategy: validation

Validate before calling

if (typeof text !== 'string') throw new Error('from_text requires a string literal, got: ' + typeof text);

Type guard

const isStringLiteral = (v) => typeof v === 'string';

Try / catch

try { compile(prql) } catch (e) { if (e.message.includes('from_text: expected a string literal')) { /* inline the data as a quoted literal */ } }

Prevention

When it happens

Trigger: Calling `from_text format:"csv" ...` where the text argument is an expression instead of a quoted literal — e.g. `from_text format:"csv" text:my_column`, concatenation, or a value read from another pipeline stage.

Common situations: Trying to load data from a column or a runtime-computed string, interpolating a variable into `from_text`, or forgetting quotes around the CSV/JSON text.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

                // yes, this is not a transform, but this is the most appropriate place for it

                let [list] = unpack::<1>(func.args);
                let list = list.kind.into_tuple().unwrap();
                let [a, b]: [Expr; 2] = list.try_into().unwrap();

                let res = maybe_binop(Some(a), &["std", "eq"], Some(b)).unwrap();
                return Ok(res);
            }

            "from_text" => {
                // yes, this is not a transform, but this is the most appropriate place for it

                let [format, text_expr] = unpack::<2>(func.args);

                let text = match text_expr.kind {
                    ExprKind::Literal(Literal::String(text)) => text,
                    _ => {
                        return Err(Error::new(Reason::Expected {
                            who: Some("std.from_text".to_string()),
                            expected: "a string literal".to_string(),
                            found: format!("`{}`", write_pl(text_expr.clone())),
                        })
                        .with_span(text_expr.span));
                    }
                };

                let res = {
                    let span = format.span;
                    let format = format
                        .try_cast(ExprKind::into_literal, Some("`format`"), "csv or json")?
                        .to_string();
                    match format.as_str() {
                        "\"csv\"" => from_text::parse_csv(&text)
                            .map_err(|r| Error::new_simple(r).with_span(span))?,
                        "\"json\"" => from_text::parse_json(&text)
                            .map_err(|r| Error::new_simple(r).with_span(span))?,

View on GitHub (pinned to e164e249b9)