wtfutil/wtf · error
query returned %d tables, expected 1: %s
Error message
query returned %d tables, expected 1: %s
What it means
RunQuery expects exactly one table from the Log Analytics response and throws this when len(res.Tables) > 1. The rendering pipeline (TableRow loop) only processes res.Tables[0], so multiple tables would silently drop data. The query text is appended after the count.
Source
Thrown at modules/azurelogs/query.go:91
},
nil)
if err != nil {
return nil, fmt.Errorf("failed to execute query on workspace %s: %w", qf.WorkspaceID, err)
}
if res.Error != nil {
return nil, res.Error
}
switch len(res.Tables) {
case 0:
return nil, fmt.Errorf("query returned no data tables: %s", qf.Query)
case 1:
if len(res.Tables[0].Columns) == 0 {
return nil, fmt.Errorf("query returned table with no columns: %s", qf.Query)
}
default:
return nil, fmt.Errorf("query returned %d tables, expected 1: %s", len(res.Tables), qf.Query)
}
// Process each row of data
for _, row := range res.Tables[0].Rows {
var r TableRow
for _, field := range row {
if field == nil {
r = append(r, "")
continue
}
// Convert all data types to string representation
switch v := field.(type) {
case string:
r = append(r, v)
case float64:
r = append(r, fmt.Sprintf("%.0f", v))View on GitHub (pinned to bb838c1ccb)
Solutions
- Reduce the query file to a single KQL statement that yields one table
- If batching is needed, split into separate query files and run each with its own Init/RunQuery
- Wrap multi-part logic into one statement using `union` or `materialize(...)` so a single table is returned
- Verify the API version in use — some responses include extra tables that older rendering code does not expect
Example fix
// before (two statements -> two tables) AzureActivity | take 10 SigninLogs | take 10 // after (single table) AzureActivity | take 10 | union (SigninLogs | take 10) // or split into two query files
Defensive patterns
Strategy: validation
Validate before calling
// reject multi-statement KQL before running
if strings.Count(qf.Query, ";") > 0 && !strings.HasSuffix(strings.TrimSpace(qf.Query), ";") == false {
// count standalone result statements
}
trimmed := strings.TrimSpace(qf.Query)
if strings.Count(trimmed, "\n") > 0 && strings.Count(strings.ReplaceAll(trimmed, ";", ""), "| ") == 0 {
return errors.New("only a single KQL statement returning one table is supported")
} Try / catch
tables, err := RunQuery(sess)
if err != nil {
if strings.Contains(err.Error(), "tables, expected 1") {
return fmt.Errorf("split the query into one statement per file: %w", err)
}
return err
} Prevention
- Keep one KQL statement per query config file
- Combine multiple sources with `union` into a single result table
- Review query files in PRs to catch pasted multi-statement queries
When it happens
Trigger: RunQuery or fetchDataAsync with KQL that legitimately produces multiple result tables — e.g. multiple batched statements separated by semicolons where more than one emits output, or `union`-style constructs returning several result sets in batch mode.
Common situations: Pasting multi-statement KQL (two SELECT-like statements) into the query file, or using features/API versions that return extra diagnostic tables alongside the main result.
Related errors
- query returned no data tables: %s
- query returned table with no columns: %s
- azure workspace ID is required but not configured
- azure subscription ID is required but not configured
- failed to create Azure Logs client for subscription %s: %w
AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03).
Data as JSON: /api/errors/d78a3a32753d27d5.
Report an issue: GitHub.