{"record":{"id":"454cd34c3a5b6722","repo":"hasura/graphql-engine","slug":"escapetargetname-only-implemented-for-tables-and","errorCode":null,"errorMessage":"`escapeTargetName` only implemented for tables and interpolated queries","messagePattern":"`escapeTargetName` only implemented for tables and interpolated queries","errorType":"exception","errorClass":"ErrorWithStatusCode","httpStatus":500,"severity":"error","filePath":"dc-agents/sqlite/src/query.ts","lineNumber":103,"sourceCode":"}\n\n/**\n *\n * @param tableName: Unescaped table name. E.g. 'Alb\"um'\n * @returns Escaped table name. E.g. '\"Alb\\\"um\"'\n */\nexport function escapeTableName(tableName: TableName): string {\n  return validateTableName(tableName).map(escapeIdentifier).join('.');\n}\n\nexport function escapeTargetName(target: Target): string {\n  switch (target.type) {\n    case 'table':\n      return escapeTableName(target.name);\n    case 'interpolated':\n      return escapeTableName([target.id]); // Interpret as CTE reference\n    default:\n      throw new ErrorWithStatusCode(\n        '`escapeTargetName` only implemented for tables and interpolated queries',\n        500,\n        { target },\n      );\n  }\n}\n\n/**\n * @param tableName\n * @returns escaped tableName string with schema qualification removed\n *\n * This is useful in where clauses in returning statements where a qualified table name is invalid SQLite SQL.\n */\nexport function escapeTableNameSansSchema(tableName: TableName): string {\n  return escapeTableName(getTableNameSansSchema(tableName));\n}\n\nexport function json_object(","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/dc-agents/sqlite/src/query.ts#L85-L121","documentation":"escapeTargetName switches on the target type and only knows how to escape `'table'` and `'interpolated'` targets (the latter via its CTE id). Any other target type — in practice `'function'` — falls into the default branch and throws an ErrorWithStatusCode(500).","triggerScenarios":"A query with a function target reaching WHERE-clause, subquery, join, or aggregate-subquery generation because it bypassed the earlier top-level type check (e.g. nested inside a relationship or reused target object).","commonSituations":"Function targets sneaking in through relationship traversal or nested query fragments rather than the top-level body; version drift between the request schema and the query builder's supported target kinds.","solutions":["Ensure every target in the request tree (including nested/relationship targets) is a table or interpolated target","Upgrade the agent — function targets should be rejected earlier with a clearer message","If you control the server, extend escapeTargetName rather than letting it hit default"],"exampleFix":"// before: nested function target\n{ type: 'function', name: 'udf' }\n// after\n{ type: 'table', name: ['main','public','materialized_view'] }","handlingStrategy":"validation","validationCode":"function assertQueryableTargetTree(q: any) { walk(q, t => { if (t?.type !== 'table' && t?.type !== 'interpolated') throw new Error(`Unsupported target: ${t?.type}`); }); }","typeGuard":"const isEscapableTarget = (t: Target): t is TableTarget | InterpolatedTarget => t.type === 'table' || t.type === 'interpolated';","tryCatchPattern":null,"preventionTips":["Walk the whole request tree (nested targets too), not just the top-level target","Add a client-side JSON-schema check on requests before dispatch"],"tags":["sqlite","query-builder","target","unsupported-feature"],"backgroundTag":"unsupported-query-target","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}