hasura/graphql-engine · error · ErrorWithStatusCode

User defined functions not supported in queries

Error message

User defined functions not supported in queries

What it means

The SQLite agent's query endpoint explicitly rejects requests whose `target.type` is `'function'`. User-defined functions are not supported as query targets because SQLite cannot treat a UDF call as a FROM-clause source the way the agent's CTE-based query generation requires. The agent returns HTTP 500 with details naming the rejected function.

Source

Thrown at dc-agents/sqlite/src/index.ts:204

  },
);

/**
 * @throws ErrorWithStatusCode
 */
server.post<{ Body: QueryRequest; Reply: QueryResponse }>(
  '/query',
  async (request, response) => {
    server.log.info(
      { headers: request.headers, query: request.body },
      'query.request',
    );
    const end = queryHistogram.startTimer();
    const config = getConfig(request);
    const body = request.body;
    switch (body.target.type) {
      case 'function':
        throw new ErrorWithStatusCode(
          'User defined functions not supported in queries',
          500,
          { function: { name: body.target.name } },
        );
      case 'interpolated': // interpolated should actually work identically to tables when using the CTE pattern
      case 'table':
        try {
          const result: QueryResponse = await queryData(
            config,
            sqlLogger,
            body,
          );
          return result;
        } finally {
          end();
        }
    }
  },

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Change the request target to a real table (`type: 'table'`) or an interpolated target (`type: 'interpolated'`)
  2. If you need computed data, materialize it into a table or use an interpolated query with a CTE
  3. Remove tracked-function entries from metadata that point at the SQLite agent

Example fix

// before
{ target: { type: 'function', name: 'top_albums', args: {...} } }
// after
{ target: { type: 'table', name: ['top_albums'] } }
Defensive patterns

Strategy: type-guard

Validate before calling

if (body.target.type === 'function') throw new Error('UDF targets unsupported by SQLite agent');

Type guard

const isSupportedTarget = (t: any): t is {type:'table'|'interpolated'} => t.type === 'table' || t.type === 'interpolated';

Try / catch

null

Prevention

When it happens

Trigger: POSTing to the query route with a body where `target: { type: 'function', name: ... }`, e.g. when a client or Hasura connector forwards a command/UDF-style target to the SQLite agent.

Common situations: Reusing a connector client built for a database that supports table functions (e.g. BigQuery, Postgres UDFs) against SQLite; metadata that models a tracked function and routes queries to it; version changes in the query API where function targets were previously silently ignored.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/934cf592ae7d9e87. Report an issue: GitHub.