ToolJet/ToolJet · error · QueryError
Could not fetch tables
Error message
Could not fetch tables
What it means
Thrown by _listAllTables (the backing implementation of invokeMethod('listTables')) when the AWS SDK's ListTablesCommand.send rejects inside the pagination loop. The loop pages through all table names using LastEvaluatedTableName with a Limit of 100, so any send failure — on any page — aborts and is wrapped as 'Could not fetch tables'. This feeds the table-picker dropdown in the editor.
Source
Thrown at plugins/packages/dynamodb/lib/index.ts:165
throw new QueryError('Method not found', `Method '${methodName}' is not supported by the DynamoDB plugin`, {});
}
private async _listAllTables(
client: DynamoDBClient,
args?: any
): Promise<{ items: Array<{ value: string; label: string }>; totalCount: number }> {
const tables: string[] = [];
let lastEvaluatedTableName: string | undefined;
try {
do {
const command = new ListTablesCommand({ ExclusiveStartTableName: lastEvaluatedTableName, Limit: 100 });
const data = await client.send(command);
tables.push(...(data.TableNames || []));
lastEvaluatedTableName = data.LastEvaluatedTableName;
} while (lastEvaluatedTableName);
} catch (err) {
throw new QueryError('Could not fetch tables', err.message, {});
}
const search = (args?.search || '').toLowerCase();
const filtered = search ? tables.filter((name) => name.toLowerCase().includes(search)) : tables;
const page = args?.page || 1;
const limit = args?.limit;
if (limit) {
const start = (page - 1) * limit;
return {
items: filtered.slice(start, start + limit).map((name) => ({ value: name, label: name })),
totalCount: filtered.length,
};
}
return {
items: filtered.map((name) => ({ value: name, label: name })),View on GitHub (pinned to 20602a8e10)
Solutions
- Grant the credential's principal dynamodb:ListTables on '*' (or at minimum the account scope) — this action is account-scoped, not table-scoped.
- Verify the region in the datasource config is the region where your tables live.
- If using instance-profile or ARN-role credentials, confirm the role trust policy and session are still valid (re-test the connection).
- Read the wrapped err.message for the specific AWS error code (AccessDeniedException vs. ThrottlingException) and act on it.
Example fix
// before — IAM policy missing ListTables
{
"Effect": "Allow",
"Action": ["dynamodb:GetItem", "dynamodb:PutItem"],
"Resource": "arn:aws:dynamodb:us-east-1:123:table/*"
}
// after — add account-scoped ListTables
{
"Effect": "Allow",
"Action": ["dynamodb:ListTables"],
"Resource": "*"
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify IAM has ListTables before opening the picker // (no in-process validation; this is a server-side permission check)
Try / catch
try { await plugin.invokeMethod('listTables', ctx, sourceOptions, args); }
catch (e) { if (e instanceof QueryError && e.message === 'Could not fetch tables') { /* show 'check dynamodb:ListTables permission' */ } else throw e; } Prevention
- Grant dynamodb:ListTables on '*' for the datasource principal.
- Confirm the configured region is reachable and correct.
- Cache the table list to avoid repeated ListTables calls.
When it happens
Trigger: The configured IAM principal lacks dynamodb:ListTables on the account/global resource. Network failure or STS/region misconfiguration reaching the DynamoDB endpoint. Throttling from excessive ListTables calls. An instance-profile or assumed-role credential that expired mid-iteration. The region in sourceOptions points at a region with no access.
Common situations: Datasource created with an IAM user that has table-level grants but not the account-level ListTables permission. EC2 instance profile credentials rotated/expired. Wrong region selected so the endpoint is unreachable or returns AccessDenied. Heavy concurrent editing sessions hammering ListTables.
Related errors
- Query could not be completed
- Failed to assume role: ${err.message}
- Method not found
- Query could not be completed
- Query could not be completed
AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13).
Data as JSON: /api/errors/33eff4c3be12155a.
Report an issue: GitHub.