jmeter-debugging
Skill5 starsChanged 6 months agoMITView on GitHub
Iterative AI-driven JMeter script debugging via smoke tests, log analysis, and targeted fixes. Use when the user asks to debug, troubleshoot, fix errors in, or validate a JMeter script, or mentions JMeter smoke testing failures.
We split this skill into the rules it gives an agent
30 rules. About 0 are common, 13 are distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈13
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Never start this workflow unless the user explicitly requests it
- Very specific: line 29
Run a 1/1/1 smoke test
- Distinctive: line 101
Ask the user for the following values.
- Distinctive: line 114
Action: Before starting the debug loop, check if this system has known issues in memory.
- Very specific: line 142
Action: Create the file artifacts/{test_run_id}/analysis/debug_manifest.md with:
- Very specific: line 178
If PerfMemory is unavailable, set pm_session_id = null and skip all subsequent PerfMemory steps.
- Very specific: line 187
Action: Call analyze_jmeter_script to generate the structure files on disk.
- Very specific: line 262
Read the JTL file at artifacts/{test_run_id}/jmeter/test-results.csv
- Very specific: line 263
Search for any row where the success column is false
- Distinctive: line 280
After stopping, wait a few seconds for JMeter threads to wind down before proceeding to log analysis.
- Distinctive: line 283
If the test completes on its own with 0% errors, proceed directly to Step 4.
- Very specific: line 285
Fallback: Only kill the PID if stop_jmeter_test fails to stop the test.
- Very specific: line 293
Action: Call analyze_jmeter_log with log_source="jmeter" (not the default):
- Distinctive: line 316
If ANY of these are true, stop debugging and go to Step 10 (Report):
- Distinctive: line 323
If errors are isolated to specific samplers:
- Very specific: line 343
If user approves a suggestion, apply it at Step 8 and save matched_attempt_id
- Distinctive: line 344
If user declines, continue to Step 6 as normal
- Very specific: line 395
Search for lines containing [ERROR]:[DEBUG]: — these contain the verbose request/response details from the debug post-processor.
- Very specific: line 410
Always use dry_run=true first, then dry_run=false to apply.
- Very specific: line 423
Read the new exported_files.json to get the refreshed node_index.
- Very specific: line 477
If iteration_count >= 5: Go to Step 10 (Report) with status "Iteration Limit Reached".
- Very specific: line 478
If iteration_count < 5: Go back to Step 3 (run a fresh smoke test).
- Distinctive: line 555
If resolved: the script is ready for load testing or BlazeMeter upload
- Distinctive: line 556
If not resolved: remaining errors and recommendation for manual investigation
- Very specific: line 568
Always use dry_run=true before applying any edit.
- Distinctive: line 570
If errors indicate environment/infrastructure issues, stop immediately and report.
- Very specific: line 571
Always use log_source="jmeter" for local smoke tests (not the default "blazemeter").
- Distinctive: line 572
Do NOT write code to fix MCP tool issues.
- Distinctive: line 573
Always maintain the debug manifest throughout the workflow.
- Very specific: line 576
If pm_session_id is null, skip all PerfMemory steps (0.5, 1.5, 5d, 8e, 10b).
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
JMeter Script Debugging
When to Use This Skill
- User explicitly asks to debug, troubleshoot, or fix a JMeter script
- User reports errors from a JMeter smoke test or test execution
- User wants to validate that a JMeter script runs cleanly
- Never start this workflow unless the user explicitly requests it
Reference
This section provides context for humans and capable models. For the step-by-step execution instructions, skip to the Execution section below.
How Debugging Works
This workflow mirrors how an experienced performance test engineer debugs a script:
- Run a 1/1/1 smoke test
- Analyze the log to find the first failure
- Attach a debug post-processor to capture full request/response details
- Re-run to capture verbose debug data
- Diagnose root cause from the debug output
- Apply a single targeted fix
- Re-test — if clean, done. If not, repeat from step 1.
Maximum 5 iterations. If not resolved after 5 cycles, stop and report.
Common Diagnosis Patterns
Missing or stale correlation values (NOT_FOUND in request body or URL):
- A dynamic value was not extracted from a prior response
- Fix: Add a JSON, Regex, or Boundary extractor to the correct sampler
Extractor on the wrong sampler (common in OAuth/SSO flows):
- The extractor logic is correct but placed under the wrong HTTP sampler
- Fix: Remove from wrong sampler, add to the correct one
Wrong request body or parameterization:
- Hardcoded values that should be parameterized
- Fix: Use
edit_jmeter_componentwithreplace_in_body
Auth token or session issues:
- Bearer token, CSRF token, or session cookie not passed correctly
- Fix: Verify extractors are on the correct sampler in the auth chain
Server-side validation errors (application error in response body):
- Request data invalid from server's perspective (duplicate, expired)
- Fix: Report to user — may need test data adjustments, not script fixes
EntraID / Microsoft Entra ID auth flows: See the jmeter-entraid-debugging skill for EntraID-specific diagnosis patterns, components, and sampler sequences.
Debug Manifest
A markdown file maintained throughout debugging to log all issues and fixes.
Location: artifacts/{test_run_id}/analysis/debug_manifest.md
The manifest is created at the start, appended after each iteration, and finalized when debugging completes. See the Execution section for the exact templates.
PerfMemory Integration
This workflow integrates with the PerfMemory lessons-learned memory layer. Before
starting a debug loop, the agent searches for similar past issues. During debugging,
each attempt is stored so future agents can learn from it. See the perfmemory skill
for full details on PerfMemory tools and workflows.
Memory is advisory — if the PerfMemory MCP server is unavailable, skip all memory-related steps and proceed with normal debugging. Do not block debugging because memory is down.
Related Rules
prerequisites.mdc—test_run_idand artifact structure validationskill-execution-rules.mdc— Follow steps in order, do not skipmcp-error-handling.mdc— MCP tool error handlingjmeter-script-guardrails.mdc— Smoke test = 1/1/1, one fix at a time, max 5 iterations, stop on environment issues
Execution
This is an iterative workflow. Steps 3-8 repeat until the script is clean or the iteration limit (5) is reached.
Collect Inputs
Ask the user for the following values. Do not proceed until all required values are collected.
REQUIRED:
test_run_id = [ask user — must have an existing JMX in artifacts/{test_run_id}/jmeter/]Step 0.5 — Memory Check (PerfMemory)
Input: test_run_id
Action: Before starting the debug loop, check if this system has known issues in memory. This is a broad check to pre-load context — specific symptom searches happen at Step 5.
0.5a. Search for past sessions related to this system:
find_similar_attempts(
symptom_text = "JMeter script debugging for {system_under_test}",
system_under_test = {system_under_test}
)0.5b. If results are returned (any similarity), note the top matches for context. These give the agent awareness of what types of issues have been seen before on this system (e.g., "this system commonly has OAuth correlation issues").
0.5c. If no results or PerfMemory is unavailable, proceed normally — this step is advisory only.
Save: memory_context (list of top match summaries, or empty)
Step 1 — Create Debug Manifest
Input: test_run_id
Action: Create the file artifacts/{test_run_id}/analysis/debug_manifest.md with:
# Debug Manifest
- **Test Run ID**: {test_run_id}
- **Script**: {jmx_filename}
- **Started**: {current timestamp YYYY-MM-DD HH:MM:SS}
- **Status**: In Progress
---Save: iteration_count = 0
Step 1.5 — Open PerfMemory Session
Input: test_run_id, jmx_filename
Action: Open a debug session in PerfMemory to track this debugging effort.
store_debug_session(
system_under_test = {system_under_test},
test_run_id = {test_run_id},
script_name = {jmx_filename},
auth_flow_type = {if known from script analysis, otherwise omit},
environment = {if known, otherwise omit},
created_by = "cursor"
)Save: pm_session_id from the response.
If PerfMemory is unavailable, set pm_session_id = null and skip all subsequent
PerfMemory steps.
Step 2 — Enforce 1/1/1 Thread Configuration
Input: test_run_id
Action: Call analyze_jmeter_script to generate the structure files on disk.
analyze_jmeter_script(
test_run_id = {test_run_id},
detail_level = "detailed"
)Save from the MCP response: exported_files — contains paths to the persisted
jmx_structure_*.json and .md files. Also save outline and summary for context.
Important: The MCP response is a summary only — it does NOT include the full
node_index or hierarchy. Read the exported JSON file at exported_files.json to
obtain the node_index, hierarchy, and variables. Use the node_index to find:
thread_group_node_id— the Thread Group node (type:ThreadGroup)udv_node_id— the User Defined Variables node (type:Arguments)sampler_list— all HTTP Sampler node_ids (type:HTTPSamplerProxy)
Check the Thread Group properties. If not set to 1/1/1, override:
edit_jmeter_component(
test_run_id = {test_run_id},
target_node_id = {thread_group_node_id},
operations = [
{"op": "set_prop", "name": "ThreadGroup.num_threads", "value": "1"},
{"op": "set_prop", "name": "ThreadGroup.ramp_time", "value": "1"},
{"op": "set_prop", "name": "LoopController.loops", "value": "1"}
],
dry_run = false
)Step 3 — Run Smoke Test
Input: test_run_id
Action:
3a. List scripts to get the JMX path:
list_jmeter_scripts(
test_run_id = {test_run_id}
)Save: jmx_path from the response.
3b. Start the test:
start_jmeter_test(
test_run_id = {test_run_id},
jmx_path = {jmx_path}
)Save: pid from the response.
3c. Monitor and stop early on errors:
get_jmeter_run_status(
test_run_id = {test_run_id},
pid = {pid}
)Poll every few seconds. When errors appear (error rate > 0%), verify errors in the JTL before stopping:
- Read the JTL file at
artifacts/{test_run_id}/jmeter/test-results.csv - Search for any row where the
successcolumn isfalse - If
success=falserows exist: Errors are confirmed. Stop the test immediately. - If NO
success=falserows exist: The error_rate was a transient JTL parsing artifact (race condition from reading the CSV while JMeter is mid-write). Ignore the error and continue polling.
The metrics.error_rate from get_jmeter_run_status can report false positives
due to this JTL read race condition. Always verify against the JTL source of truth.
Once errors are confirmed in the JTL, stop the test:
stop_jmeter_test(
test_run_id = {test_run_id}
)After stopping, wait a few seconds for JMeter threads to wind down before proceeding to log analysis. Thread shutdown is not instantaneous.
If the test completes on its own with 0% errors, proceed directly to Step 4.
Fallback: Only kill the PID if stop_jmeter_test fails to stop the test.
Step 4 — Analyze Log
Input: test_run_id
Action: Call analyze_jmeter_log with log_source="jmeter" (not the default):
analyze_jmeter_log(
test_run_id = {test_run_id},
log_source = "jmeter"
)Save: error_rate and first_failing_sampler from the response.
Step 5 — Triage
Input: error_rate, first_failing_sampler, log analysis output
Decision gate — choose ONE path:
Path A — Script is clean (0% error rate):
- Go to Step 9 (Cleanup).
Path B — Environment/systemic issue (stop immediately): If ANY of these are true, stop debugging and go to Step 10 (Report):
- HTTP 401/403 on login/auth samplers
- HTTP 5xx on all or most samplers
- Connection refused/timeout on all samplers
- Repeated identical errors across all samplers
Path C — Script issue (continue debugging): If errors are isolated to specific samplers:
5d. Memory-assisted triage — Before proceeding to Step 6, search PerfMemory for
this specific symptom (skip if pm_session_id is null):
find_similar_attempts(
symptom_text = {build structured symptom from the error — see perfmemory skill
for the template},
system_under_test = {system_under_test},
error_category = {error category from log analysis}
)If recommendation = apply_known_fix (similarity > 0.85):
- Skip Step 6 and Step 7 — apply the known fix directly at Step 8
- Save
matched_attempt_idfrom the top match for Step 8e
If recommendation = review_suggestions (similarity 0.60 - 0.85):
- Present the top matches to the user for review
- If user approves a suggestion, apply it at Step 8 and save
matched_attempt_id - If user declines, continue to Step 6 as normal
If recommendation = no_match:
- Continue to Step 6 as normal.
Step 6 — Attach Debug Post-Processor
Input: test_run_id, first_failing_sampler node_id
Action:
6a. Enable verbose logging:
edit_jmeter_component(
test_run_id = {test_run_id},
target_node_id = {udv_node_id},
operations = [{"op": "set_prop", "name": "VERBOSE_LOGGING", "value": "true"}],
dry_run = false
)6b. Add the built-in debug post-processor to the first failing sampler:
add_jmeter_component(
test_run_id = {test_run_id},
component_type = "jsr223_debug_postprocessor",
parent_node_id = {first_failing_sampler_node_id},
component_config = {},
dry_run = false
)Save: debug_postprocessor_node_id from the response.
Step 7 — Debug Smoke Test and Diagnose
Input: test_run_id
Action:
7a. Re-run the smoke test (same as Step 3, including early stop on errors).
7b. Run analyze_jmeter_log(test_run_id, log_source="jmeter") again.
7c. Read the raw JMeter log at artifacts/{test_run_id}/jmeter/{test_run_id}.log.
Search for lines containing [ERROR]:[DEBUG]: — these contain the verbose
request/response details from the debug post-processor.
Diagnose the root cause using the debug output. See the Common Diagnosis Patterns in the Reference section.
Step 8 — Apply Fix and Iterate
Input: test_run_id, diagnosis from Step 7
Action:
8a. Apply a single targeted fix using add_jmeter_component or edit_jmeter_component.
Always use dry_run=true first, then dry_run=false to apply.
8b. Re-analyze the script to refresh the persisted structure files with the latest node_ids after the fix. Read the updated exported JSON file for node lookups in subsequent iterations:
analyze_jmeter_script(
test_run_id = {test_run_id},
detail_level = "detailed"
)Read the new exported_files.json to get the refreshed node_index.
8c. Increment iteration_count = iteration_count + 1
8d. Append to the debug manifest:
## Iteration {iteration_count} — {current timestamp}
### Error Identified
- **Sampler**: {sampler_name}
- **Response Code**: {code}
- **Error Message**: {message}
### Diagnosis
{description of root cause}
### Fix Applied
{description of fix and which component was added/edited}
### Result After Fix
{to be filled after re-test}
Completed at {current timestamp}.8e. Store attempt in PerfMemory (skip if pm_session_id is null):
store_debug_attempt(
session_id = {pm_session_id},
iteration_number = {iteration_count},
symptom_text = {structured symptom — see perfmemory skill for template},
outcome = {resolved | failed | environment_issue | test_data_issue |
authentication_issue | needs_investigation},
error_category = {from log analysis},
severity = {Critical | High | Medium},
response_code = {HTTP status code or exception},
hostname = {hostname where error occurred},
sampler_name = {failing sampler name},
api_endpoint = {failing URL},
diagnosis = {root cause from Step 7},
fix_description = {what was applied in Step 8a},
fix_type = {add_extractor | move_extractor | edit_request_body |
edit_header | edit_correlation | other},
component_type = {json_extractor | regex_extractor | jsr223_postprocessor |
jsr223_preprocessor | http_sampler | test_plan | other},
matched_attempt_id = {if a memory match was applied, its attempt_id — otherwise omit}
)Save: last_attempt_id from the response.
8f. Decision gate:
- If
iteration_count>= 5: Go to Step 10 (Report) with status "Iteration Limit Reached". - If
iteration_count< 5: Go back to Step 3 (run a fresh smoke test).
Step 9 — Cleanup (script is clean)
Input: test_run_id, debug_postprocessor_node_id(s)
Action:
9a. Disable each debug post-processor (do NOT delete):
edit_jmeter_component(
test_run_id = {test_run_id},
target_node_id = {debug_postprocessor_node_id},
operations = [{"op": "toggle_enabled"}],
dry_run = false
)9b. Set verbose logging back to false:
edit_jmeter_component(
test_run_id = {test_run_id},
target_node_id = {udv_node_id},
operations = [{"op": "set_prop", "name": "VERBOSE_LOGGING", "value": "false"}],
dry_run = false
)9c. Run one final 1/1/1 smoke test (same as Step 3) to confirm the script is clean with debug artifacts disabled. This validation run should complete fully since we expect 0% errors. If errors still appear, stop the test early and return to Step 5.
9d. Go to Step 10 (Report) with status "Resolved".
Step 10 — Finalize and Report
Input: test_run_id, iteration_count, final status
Action:
10a. Update the debug manifest header Status and append:
## Final Summary
- **Started**: {start timestamp}
- **Completed**: {current timestamp}
- **Total Duration**: {elapsed time}
- **Total Iterations**: {iteration_count}
- **Final Status**: {Resolved | Needs Human Intervention | Iteration Limit Reached}
- **Fixes Applied**:
1. {fix description}
2. {fix description}10b. Close PerfMemory session (skip if pm_session_id is null):
close_debug_session(
session_id = {pm_session_id},
final_outcome = {resolved | unresolved | environment_issue |
test_data_issue | authentication_issue |
iteration_limit_reached | needs_investigation},
resolution_attempt_id = {last_attempt_id if resolved, otherwise omit},
notes = {brief summary of outcome}
)10c. Tell the user:
- Total debug iterations and elapsed time
- Fixes applied (sampler name, issue, resolution)
- Final smoke test result
- If resolved: the script is ready for load testing or BlazeMeter upload
- If not resolved: remaining errors and recommendation for manual investigation
- Debug manifest location:
artifacts/{test_run_id}/analysis/debug_manifest.md - Whether lessons were stored in PerfMemory (and session_id for reference)
Error Handling
These rules apply to every step:
- Smoke tests MUST use 1 thread, 1 second ramp-up, 1 loop. No exceptions.
- Fix only the first failing sampler per iteration. Do not batch-fix.
- Always use
dry_run=truebefore applying any edit. - Maximum 5 debug iterations. Stop and report if not resolved.
- If errors indicate environment/infrastructure issues, stop immediately and report.
- Always use
log_source="jmeter"for local smoke tests (not the default"blazemeter"). - Do NOT write code to fix MCP tool issues.
- Always maintain the debug manifest throughout the workflow.
- PerfMemory is advisory only — if any PerfMemory tool call fails, log the error and continue debugging. Never block the debug loop because memory is unavailable.
- If
pm_session_idis null, skip all PerfMemory steps (0.5, 1.5, 5d, 8e, 10b).
In this repository23 other files it gives its agents.
- .cursor/rules/browser-automation-guardrails.mdcCursor rule
- .cursor/rules/implementation-standards.mdcCursor rule
- .cursor/rules/jmeter-script-guardrails.mdcCursor rule
- .cursor/rules/mcp-error-handling.mdcCursor rule
- .cursor/rules/prerequisites.mdcCursor rule
- .cursor/rules/project-and-coding-guidelines.mdcCursor rule
- .cursor/rules/skill-execution-rules.mdcCursor rule
- .cursor/rules/technology-reference-policy.mdcCursor rule
- ado-test-case-conversionSkill
- comparison-report-workflowSkill
- jmeter-correlation-namingSkill
- jmeter-entraid-debuggingSkill
- jmeter-har-conversionSkill
- jmeter-hitl-editingSkill
- jmeter-script-validatorSkill
- jmeter-swagger-conversionSkill
- msteams-notificationSkill
- perfmemorySkill
- performance-testing-workflowSkill
- playwright-browser-automationSkill
- report-revision-workflowSkill
- sharepoint-uploadSkill
- subagent-orchestratorSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

