Common Error Messages
Note
Quick reference for understanding and fixing the most common NQL error messages.
Overview
NQL error messages can be cryptic. This guide explains the most common errors, what causes them, and how to fix them quickly.
Critical Syntax Errors
"Cannot use compute after summarize"
Meaning: You're trying to calculate values using variables from a summarize clause in a subsequent compute clause.
Common cause: Attempting to reference summarize variables outside the summarize block.
Example of the error:
/* ❌ WRONG - This will fail */
execution.events during past 7d
| summarize
total_cpu = cpu_time.sum(),
total_duration = execution_duration.sum()
| compute cpu_percent = (total_cpu * 100) / total_duration # ERROR!
Fix: Move all calculations inline within the summarize clause itself.
/* ✅ CORRECT - Calculation inside summarize */
execution.events during past 7d
| summarize
cpu_percent = ((cpu_time.sum()) * 100) / execution_duration.sum()
The Rule
NEVER use compute after summarize. All calculations must be inline within the summarize clause.
"Field 'X' not found in context"
Meaning: The field you're referencing doesn't exist in the current query context.
Common causes: 1. Typo in field name - Check spelling and capitalization 2. Wrong table context - Field doesn't exist on the table you're querying 3. Missing join - Field requires include or with clause first 4. Wrong namespace - Using device.field when you should use context.field or vice versa
Examples of the error:
/* ❌ WRONG - device field on events without proper context */
execution.events during past 7d
| where device.hardware.memory > 8GB # ERROR!
/* ✅ CORRECT - use context for event-time values */
execution.events during past 7d
| where context.hardware_memory > 8GB
/* ✅ CORRECT - or start with devices and join events */
devices
| with execution.events during past 7d
| where device.hardware.memory > 8GB
Quick check: See Field Reference to verify the field exists on your table.
"Time window required for event table"
Meaning: Event tables (execution.events, connection.events, etc.) require a time specification.
Example of the error:
Fix: Add during past Xd or during past Xh:
Always Add Time Windows
Get in the habit of typing during past 7d immediately after event table names.
"Cannot reference variable within same summarize clause"
Meaning: You're trying to use a variable you just defined within the same summarize block.
Example of the error:
/* ❌ WRONG - referencing total_failures in same clause */
| summarize
total_failures = (sum1 + sum2),
failure_rate = total_failures / total_attempts # ERROR!
Fix: Repeat the full calculation instead of referencing the variable:
/* ✅ CORRECT - repeat the calculation */
| summarize
total_failures = (sum1 + sum2),
failure_rate = (sum1 + sum2) / total_attempts
Performance Errors
"Query timeout exceeded" or "Query too complex"
Meaning: Your query is taking too long to execute (typically >60 seconds).
Common causes: 1. No early filtering - Processing too much data 2. Time window too large - Querying past 30d on execution.events without filters 3. Multiple includes without limits - Each include multiplies query complexity 4. Complex calculations on large datasets - Expensive operations without narrowing data first
Examples and fixes:
/* ❌ SLOW - no filters on large dataset */
execution.events during past 30d
| summarize count by binary.name # Processes ALL events first!
/* ✅ FAST - filter early */
execution.events during past 30d
| where binary.name in ["outlook.exe", "chrome.exe", "teams.exe"]
| summarize count by binary.name
/* ❌ SLOW - huge time window */
execution.events during past 30d
| where binary.name = "outlook.exe"
| summarize count by device.name
/* ✅ FAST - reduce time window during development */
execution.events during past 7d # Use smaller window first
| where binary.name = "outlook.exe"
| summarize count by device.name
| limit 10 # Add limit during testing
Development Strategy
- Start with
past 1dorpast 2dduring development - Add
| limit 10to see results quickly - Remove limits and expand time window when query is optimized
See: Query Performance Guide for detailed optimization techniques.
"Exceeded retention limit"
Meaning: You're trying to query data beyond the retention period.
Retention limits:
- execution.events / connection.events:
- 8 days for high-res (
past Xh,past Xmin) - 30 days for low-res (
past Xd) - Most other event tables: 30 days standard retention
Example of the error:
/* ❌ May fail - exceeds 8-day high-res limit */
execution.events during past 15d
| where binary.name = "outlook.exe"
/* ✅ CORRECT - within limits */
execution.events during past 7d
| where binary.name = "outlook.exe"
Remember Retention Limits
- High-res queries (
past Xh): Max 8 days for execution.events/connection.events - Low-res queries (
past Xd): Max 30 days for execution.events/connection.events
Data Type Errors
"Invalid operator for data type"
Meaning: You're using an operator that doesn't work with the field's data type.
Common examples:
- Using
>or<on string fields - Doing math on non-numeric fields
Examples and fixes:
/* ❌ WRONG - comparing strings with > */
devices
| where device.name > "SERVER" # Doesn't work as expected
/* ✅ CORRECT - use wildcards for string matching */
devices
| where device.name = "SERVER*"
/* ❌ WRONG - math on string field */
devices
| compute total = device.name + device.os # ERROR!
/* ✅ CORRECT - use proper numeric fields */
execution.events during past 7d
| compute total_cpu = cpu_time + gpu_time
Quick check: See Field Reference to verify field data types.
Logic Errors (Query Runs, Wrong Results)
Using count() on Sampled Events
Problem: count() on event tables returns the number of samples, not meaningful business metrics.
Example of the problem:
/* ❌ BAD - Returns sample count (not useful!) */
execution.events during past 7d
| summarize total_events = count()
/* Returns: 1,245,892 (sample count - meaningless!) */
Fix: Count unique objects instead:
/* ✅ CORRECT - Count unique objects */
execution.events during past 7d
| summarize
unique_devices = device.count(),
unique_applications = application.count(),
unique_users = user.count()
/* Returns: 142 devices, 38 apps, 156 users (business value!) */
Or: Sum actual metrics:
/* ✅ CORRECT - Sum actual metrics */
execution.events during past 7d
| summarize
total_cpu_time = cpu_time.sum(),
total_memory_used = real_memory.sum()
Never Use count() on Events
Sampled events represent periodic measurements, not discrete occurrences. Use device.count(), application.count(), or field.sum() instead.
Confusing past 2d with past 48h
Problem: These are NOT equivalent and return different data!
| Aspect | past 2d | past 48h |
|---|---|---|
| Resolution | Daily aggregated | 5-15 minute samples |
| Timezone | Cloud instance timezone | User's browser timezone |
| Precision | Full calendar days | Exact hour intervals |
Example showing the difference:
/* Query 1: past 2d (low-res, cloud timezone) */
execution.events during past 2d
| summarize count = count()
/* Returns: Different range than past 48h! */
/* Query 2: past 48h (high-res, user timezone) */
execution.events during past 48h
| summarize count = count()
/* Returns: Different range and more granular data! */
Fix: Choose based on your need: - Use past Xd for: Trends, reports, dashboards - Use past Xh for: Troubleshooting, recent analysis, incident investigation
Query Debugging Workflow
When you encounter an error, follow these steps:
Step 1: Read the Error Message Carefully
- Look for specific field names mentioned
- Note if it mentions "syntax", "field", "timeout", or "retention"
Step 2: Check Basic Syntax
□ Time window specified for event tables?
□ Clauses in correct order?
□ Parentheses balanced in calculations?
□ Field names spelled correctly?
Step 3: Simplify the Query
Start with the minimal query and add complexity one step at a time:
/* Stage 1: Base table only */
execution.events during past 1d
| limit 10
/* Stage 2: Add primary filter */
execution.events during past 1d
| where binary.name = "outlook.exe"
| limit 10
/* Stage 3: Add aggregation (simple) */
execution.events during past 1d
| where binary.name = "outlook.exe"
| summarize count = count()
/* Stage 4: Add calculations (if needed) */
execution.events during past 1d
| where binary.name = "outlook.exe"
| summarize
avg_memory = real_memory.avg(),
device_count = device.count()
/* Stage 5: Expand time window */
execution.events during past 7d
| where binary.name = "outlook.exe"
| summarize
avg_memory = real_memory.avg(),
device_count = device.count()
Step 4: Validate Data Exists
/* Remove all filters and check if base table has data */
execution.events during past 1d
| limit 5
/* If this returns nothing, no data exists in past day */
Step 5: Check Common Patterns
□ Using count() on events? → Use device.count() instead
□ Referencing variables in same summarize? → Repeat full calculation
□ Using compute after summarize? → Move calculation inside summarize
□ Querying past 2d vs past 48h? → Understand timezone differences
□ Missing by in time-series trend? → Add by 1h or by 1d
Quick Debugging Checklist
Copy this for every query issue:
□ Time window specified for event tables
□ Clauses in correct order (where → with/include → compute → summarize → list → sort → limit)
□ Field names verified in Field Reference
□ Within retention limits (8 days high-res, 30 days low-res)
□ Tested incrementally from simple to complex
□ Used | limit 10 during development
□ Filters not too restrictive (returns some data)
□ No compute after summarize
□ No variable references within same summarize clause
Related Topics
- NQL Basics - Understanding core concepts
- Query Performance Guide - Optimization techniques
- Field Reference - Valid fields per table
- with vs include - Common source of confusion
Additional Resources
- NQL Syntax Cheat Sheet - Quick syntax reference
- Query Debugging Workflow - Step-by-step debugging