How to Debug *verify-subtask Failures Across Different Verification Types in aiox-core
Enable the --verbose flag and inspect the verification block in your implementation.yaml to surface the exact error from the command, API, browser, or e2e runner.
When *verify-subtask fails in the SynkraAI/aiox-core repository, the root cause typically hides inside the verification configuration or the type-specific runner dispatched by the SubtaskVerifier class. This guide walks you through a systematic debugging workflow that works for command, api, browser, and e2e verification types.
Understand the Verification Flow
The *verify-subtask logic lives in .aiox-core/infrastructure/scripts/subtask-verifier.js. The high-level execution flow follows these steps:
- Load implementation via
loadImplementation()parsingimplementation.yaml - Locate subtask via
findSubtask()using the provided ID - Read verification metadata (type, command, URL, selector, etc.)
- Dispatch to runner via
_runVerification()which calls one of four private methods:_verifyCommand,_verifyApi,_verifyBrowser, or_verifyE2E
// Dispatch based on verification.type
// Source: subtask-verifier.js, lines 46-50
await this._runVerification(verification);
Each runner returns an object with {passed, output?, error?}. If passed is false, the verifier wraps the failure with the subtask ID, verification type, attempt count, and error message, then generates a report via generateReport().
Enable Verbose Logging
The SubtaskVerifier captures every step in an internal logs array through the _log() method. By default these logs are silent; enabling --verbose (-v) prints timestamps, command outputs, API status codes, Playwright navigation events, and retry delays to the console.
subtask-verifier 1.1 -i docs/stories/STORY-42/plan/implementation.yaml -v
All verbose output also appears in the final report under the Logs section, making it the first diagnostic tool to enable when a verification fails.
Debug Failures by Verification Type
Command Verification Failures
Implementation: _verifyCommand() at lines 68-98 of subtask-verifier.js.
Common symptoms and fixes:
- "Exit code 1" or non-zero exit: The
commandstring in the subtask'sverificationblock contains a wrong path, missing binary, or permission error. Re-run the command manually in the same working directory (--cwddefaults toprocess.cwd()). - "Command timed out": The process exceeds the default 60-second timeout. Increase the limit with
--timeout <ms>or optimize the script. - "No output captured": The script writes only to stderr or uses streaming output. The verifier captures both
stdoutandstderr; inspect theoutputfield in the failure report.
Compare the manual command output against the verifier's log entries (look for _log('Running command…')) to isolate environment differences.
API Verification Failures
Implementation: _verifyApi() at lines 33-41 of subtask-verifier.js.
Common symptoms and fixes:
- "Expected status 200, got 500": The endpoint is unreachable or the server returned an error. Verify reachability with
curlor a browser. - "Output did not match pattern": The
expectedOutputregex fails against the response body. Test your regex manually:node -e "console.log(/pattern/.test(JSON.stringify(response)))". - "Request timed out": Network latency or firewall rules block the request. Increase
--timeoutor test withcurl --max-time. - "fetch is undefined": You are running Node.js < 18 without native fetch. Install
node-fetchor upgrade Node.
The verifier logs the URL, method, and status via _log('Calling API…'). Replicate the exact request with matching headers to see the raw response.
Browser Verification Failures
Implementation: _verifyBrowser() (method starts at line 4 of its definition block).
Common symptoms and fixes:
- "Browser verification requires Playwright": The Playwright dependency is missing. Install with
npm i playwrightornpx playwright install. - "Selector not found": The CSS or XPath selector is invalid or the page loads too slowly. Open the target URL in a browser, inspect the element, and verify the selector syntax.
- "Expected text not found": Dynamic content renders after the check. Add
waitForSelectoror increaseconfig.timeoutin the verification block. - "Navigation failed / network idle timeout": Page redirects, authentication walls, or CSP headers block automation. Check console logs for navigation errors; temporarily add
page.screenshot()to the verification config to capture the UI state.
The verifier prints "Running browser verification with Playwright…" followed by the target URL and selector checks. Copy the Playwright block from subtask-verifier.js into a local script to step through each action interactively.
E2E Verification Failures
Implementation: _verifyE2E() at lines 78-89, which forwards to _verifyCommand() using the testCommand parameter.
Debugging approach:
Since E2E delegates to the command runner, follow the same steps as Command Verification. Additionally, run the testCommand manually (e.g., npm run test:e2e) and confirm the test runner returns exit code 0 on success. Check for Jest, Playwright Test, or other framework-specific errors in the captured output.
Adjust Retry Logic for Transient Errors
SubtaskVerifier retries failed attempts up to maxRetries (default 3). Retries only occur when _isTransientError(error) returns true, matching patterns like ECONNRESET, ETIMEDOUT, or ECONNREFUSED (see lines 96-105).
If verification fails after all retries, the final report shows the attempt count and last error. Increase resilience against flaky networks or CI resource contention by adjusting the retry and timeout parameters:
subtask-verifier 1.2 -i impl.yaml --retries 5 --timeout 120000
Use Programmatic Debugging
Embed the SubtaskVerifier class directly in a Node.js script to capture the raw VerificationResult object for inspection:
// file: debug-subtask.js
const { SubtaskVerifier } = require('./.aiox-core/infrastructure/scripts/subtask-verifier');
(async () => {
const verifier = new SubtaskVerifier({
implementationPath: 'docs/stories/STORY-42/plan/implementation.yaml',
verbose: true,
});
const result = await verifier.verify('1.1'); // <- subtask ID
console.log(JSON.stringify(result, null, 2)); // inspect error, output, attempts
})();
The returned object follows the JSDoc shape defined at lines 44-53 of subtask-verifier.js, exposing result.error, result.output, result.attempts, and other metadata for automated analysis.
Summary
- The
*verify-subtaskcommand delegates to four type-specific runners (_verifyCommand,_verifyApi,_verifyBrowser,_verifyE2E) inside.aiox-core/infrastructure/scripts/subtask-verifier.js. - Enable
-vto expose timestamps, API status codes, Playwright actions, and command output in the failure report. - For each verification type, validate the underlying action manually (run the shell command,
curlthe endpoint, open the browser URL, execute the test suite) before adjusting configuration. - Increase
--timeoutand--retrieswhen encountering transient network or resource errors detected by_isTransientError(). - Use the programmatic API to capture raw
VerificationResultobjects for custom CI integrations or deep debugging.
Frequently Asked Questions
How do I identify which verification type is failing?
Check the Error line in the generated report or the verbose logs. The SubtaskVerifier logs the verification type via _runVerification() before dispatching to _verifyCommand, _verifyApi, _verifyBrowser, or _verifyE2E. The subtask's verification block in implementation.yaml also explicitly declares the type field.
Why does my API verification fail with "fetch is undefined"?
The subtask-verifier.js script uses the native Node.js fetch API. If you see this error, you are running Node.js version < 18. Upgrade to Node 18+ or install a fetch polyfill (npm i node-fetch) to resolve the issue.
Can I increase the timeout for a single slow subtask without affecting others?
Yes. Pass the --timeout flag with a millisecond value when invoking the CLI for that specific subtask: subtask-verifier <id> -i <yaml> --timeout 120000. This overrides the default 60-second limit for that execution only.
Where can I find the raw output from a failed command verification?
The VerificationResult object includes an output field containing both stdout and stderr. When running programmatically, inspect result.output. When using the CLI with -v, the logs section of the report prints the captured output immediately after the _log('Running command…') entry.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →