nocobase/nocobase · error
Only select query allowed
Error message
Only select query allowed
What it means
The charts query runner whitelists read-only statements: SQL must start with SELECT or be a WITH ... SELECT CTE. Anything else (UPDATE, DELETE, INSERT, DROP, etc.) is rejected to prevent the charting feature from mutating data.
Source
Thrown at packages/plugins/@nocobase/plugin-charts/src/server/query.ts:35
return options.data || [];
},
sql: async (
options,
{
db,
transaction,
skipError,
validateSQL,
}: { db: Database; transaction?: any; skipError?: boolean; validateSQL?: boolean },
) => {
try {
// 分号截取,只取第一段
const sql: string = options.sql.trim().split(';').shift();
if (!sql) {
throw new Error('SQL is empty');
}
if (!/^select/i.test(sql) && !/^with([\s\S]+)select([\s\S]+)/i.test(sql)) {
throw new Error('Only select query allowed');
}
const [data] = await db.sequelize.query(sql, { transaction });
return data;
} catch (error) {
if (skipError) {
return [];
}
throw error;
}
},
};
export default query;
View on GitHub (pinned to fa42722fef)
Solutions
- Rewrite the query to return data with SELECT (or WITH ... SELECT)
- Move any write/maintenance logic out of chart queries into server code or migrations
- If aggregates are needed, wrap the logic in a DB view and SELECT from it
Example fix
// before const sql = "UPDATE charts SET x = 1"; // after const sql = "SELECT id, x FROM charts";
Defensive patterns
Strategy: validation
Validate before calling
const first = sql.trim().split(';')[0];
if (!/^select/i.test(first) && !/^with[\s\S]+select[\s\S]+/i.test(first)) {
throw new Error('Chart SQL must be a SELECT or WITH...SELECT statement');
} Type guard
function isReadOnlySql(sql: string): boolean {
const s = sql.trim().split(';')[0];
return /^select/i.test(s) || /^with[\s\S]+select[\s\S]+/i.test(s);
} Try / catch
try {
const data = await query(sql);
} catch (e) {
if (e.message === 'Only select query allowed') {
message.error('Only SELECT queries are allowed in charts');
return [];
}
throw e;
} Prevention
- Write chart queries as SELECT or WITH...SELECT only
- Never put DML/DDL in chart measures
- Wrap complex logic in a DB view and SELECT from it
- Remember only the first semicolon-delimited statement is checked
When it happens
Trigger: A chart query configured with a non-select statement, or SQL whose first statement is not SELECT/WITH (note the regex only inspects the first semicolon-delimited statement).
Common situations: Developers pasting maintenance SQL into charts; building charts on stored procedures or DML; trying to run EXPLAIN-style or multi-statement scripts through the chart UI.
Related errors
- Only supports SELECT statements or WITH clauses
- SQL is empty
- SQL statements contain dangerous keywords
- Imported archive package name "${packageName}" resolves outs
- SQL cannot be empty
AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01).
Data as JSON: /api/errors/cdb1f852befdb1d1.
Report an issue: GitHub.