Skip to content

Errors and troubleshooting ​

When a statement is wrong, TypeSQL reports a compile error on the SQL string. This page shows how to read it, and what to do when TypeSQL can't type a statement.

Reading errors ​

ts
sql("SELECT emial FROM users");

The error has two parts:

  • The message uses the database's wording, so it reads like the error you would get at runtime.
  • The position (1) is the index of the offending token, counting words, operators and literals from 0. Here, emial is token 1.

Common messages ​

MistakeMessage
unknown columncolumn "emial" does not exist. Perhaps you meant the column "email"?
unknown tablerelation "post" does not exist. Perhaps you meant the relation "posts"?
unknown functionfunction slugify(text) does not exist. Declare it in the schema's $functions or in FunctionCatalog (see functions)
ambiguous columncolumn reference "id" is ambiguous
bad aliasmissing FROM-clause entry for table "x"
syntaxsyntax error at or near garbage, syntax error at end of input (see Postgres compatibility)
missing NOT NULL columnnull value in column "email" of relation "users" violates not-null constraint
writing to a viewcannot insert into view "user_stats"
DEFAULT outside a VALUES item or SET valueDEFAULT is not allowed in this context
a column assigned twicemultiple assignments to same column "email" (UPDATE), column "email" specified more than once (INSERT)
set operation widtheach UNION query must have the same number of columns
wrong inline valueparameter $1: a string value cannot be used as int4
inline value of the wrong shapeparameter $1: a { theme: "blue" } value cannot be used as jsonb (expected { theme: "dark" | "light" } | null)
JSON value outside JSONparameter $1: a sql.json() value cannot be used as text NOT NULL
raw array for JSONparameter $1: an array for jsonb NOT NULL must be passed as sql.json(value) …
non-literal SQLthe SQL text is not a string literal: …

Wrong arguments ​

A wrong positional argument is an ordinary TypeScript error on that argument:

ts
sql("SELECT id FROM users WHERE id = $1", "7");

A raw array passed to a JSON parameter fails with … parameter of type 'NonArrayOrSqlJson<Item[]>'. Pass sql.json(value) instead; see JSON values.

A statement that does not validate accepts any arguments, so its SqlError is the only error on the call.

Long statements ​

TypeScript shortens long types in error messages (a … after a few hundred characters), which can cut off the SQL text. The SqlError comes first so it stays visible, and the second line of the error repeats it:


Argument of type 'string' is not assignable to parameter of type 'SqlError<"parameter $6: a
  string[] value cannot be used as timestamptz[] NOT NULL", 63> & "INSERT INTO …'.
  Type 'string' is not assignable to type 'SqlError<"parameter $6: …", 63>'.

TIP

Set "noErrorTruncation": true in tsconfig.json to see the whole statement.

Argument of type 'string' appears for template literals with ${sql.param(…)}, because TypeScript prints the template's widened type in the message. The text was still analysed, and the SqlError is the real error.

When TypeSQL can't type a statement ​

Use sql.as<Row>(text, …). It skips inference and takes the row type you give it:

ts
const page = sql.as<{ id: number; email: string }>("FETCH 10 FROM user_cursor");

Use it for SQL that TypeSQL does not support or cannot type (here, a FETCH from a cursor declared in another statement), and for SQL it cannot see at compile time (dynamic SQL). It accepts interpolated fragments, :name and inline parameters, like sql(). With CasePlugin, write the row with camelCase keys.

Unsupported syntax is always a compile error, never a silent any. See Limits.

Exporting queries from another package (TS2883) ​

With declaration output, TypeScript 7.1 checks that every inferred type can be named from the package that exports it. Rows are plain object types, but a Query, Fragment or Migrations value is a TypeSQL type. A package that exports one without depending on @typesql/core itself fails:


error TS2883: The inferred type of 'userQuery' cannot be named without a reference to 'Query'
  from '../../shared/node_modules/@typesql/core/dist'. This is likely not portable.

Any of these fixes it:

  • Re-export TypeSQL's types from the module that calls createSql. TypeScript then names them through that module:
    ts
    export const sql = createSql<DB>(executor);
    export type * from "@typesql/core";
    export type * from "@typesql/core/postgres";
  • Add @typesql/core to the exporting package's dependencies.
  • Export the rows (execute* results) instead of the query, or annotate the return type.