Summary
createPRCommentBatch calls Object.keys(batchFixResults.results) without checking that batchFixResults.results exists. When the /fix/v1/project/{id}/batch_results response for a batch run doesn't include a results map, the action throws inside an un-awaited async call. Because it's un-awaited, the throw becomes an unhandled promise rejection and crashes the whole Node process — failing the job even though scanning, upload, and fix generation all completed successfully.
Version
Reproduced on main @ b79dd2e730f65553f692173e21c3bef4c3a7d15f (currently tagged v1.0.5, the latest release).
Stack trace
TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at .../dist/index.js:140205:45
at Generator.next (<anonymous>)
at .../dist/index.js:140098:71
at new Promise (<anonymous>)
at __webpack_modules__.40239.__awaiter (.../dist/index.js:140094:12)
at createPRCommentBatch (.../dist/index.js:140203:12)
at .../dist/index.js:142370:74
at Generator.next (<anonymous>)
at fulfilled (.../dist/index.js:142023:58)
Node.js v20.20.2
Repro conditions
- Inputs:
fixType: batch, prComment: true, codeSuggestion: true, createPR: true
- Triggered on
pull_request; Veracode GitHub App not installed on the repo, so shouldUseGitHubApp resolves to false and the "traditional PR comments" branch runs.
- Batch had 5 findings (all CWE-78) across 2 source files. Upload,
batch_status polling (hasMore: true → false), and pullBatchFixResults all completed normally, and batch_fix_results.json was written and uploaded as an artifact successfully. But the parsed object's .results key was missing/null — most likely because the fix engine didn't generate a usable patch for any of the submitted CWE-78 findings, and the API response omits results in that case rather than returning an empty object.
Where it breaks
src/create_pr_comment.ts:
export async function createPRCommentBatch(batchFixResults:any, options:any, flawArray:any){
const batchFixResultsCount = Object.keys(batchFixResults.results).length; // throws if .results is undefined/null
The same unguarded assumption (batchFixResults.results always exists) appears in several other places:
src/run_batch.ts — the codeSuggestion block, and filterEmptyPatchesFromBatch
src/checkRun.ts
src/pr_comment_handler.ts
Also, in run_batch.ts, createPRCommentBatch(batchFixResults, options, flawArray) is called without await. A synchronous throw at the top of that async function therefore becomes an unhandled rejection instead of something the caller can catch — which is why it takes down the whole process instead of failing just that one step gracefully.
Suggested fix
Guard each call site for the "batch completed but produced zero usable results" case, e.g.:
export async function createPRCommentBatch(batchFixResults:any, options:any, flawArray:any){
if (!batchFixResults?.results || Object.keys(batchFixResults.results).length === 0) {
console.log('No batch fix results to comment on — skipping PR comments.')
return
}
const batchFixResultsCount = Object.keys(batchFixResults.results).length;
...
and add await before the createPRCommentBatch(...) call in run_batch.ts so errors there can't become unhandled rejections.
Impact
On a repo where branch protection requires this check to pass, a scan that finds real vulnerabilities but for which the fixer can't generate any patch turns into a hard job/process crash rather than a clean "no auto-fix available" outcome — much worse UX than just reporting zero fixes generated.
Happy to open a PR with the guard clauses if that's useful.
Summary
createPRCommentBatchcallsObject.keys(batchFixResults.results)without checking thatbatchFixResults.resultsexists. When the/fix/v1/project/{id}/batch_resultsresponse for a batch run doesn't include aresultsmap, the action throws inside an un-awaited async call. Because it's un-awaited, the throw becomes an unhandled promise rejection and crashes the whole Node process — failing the job even though scanning, upload, and fix generation all completed successfully.Version
Reproduced on
main@b79dd2e730f65553f692173e21c3bef4c3a7d15f(currently taggedv1.0.5, the latest release).Stack trace
Repro conditions
fixType: batch,prComment: true,codeSuggestion: true,createPR: truepull_request; Veracode GitHub App not installed on the repo, soshouldUseGitHubAppresolves tofalseand the "traditional PR comments" branch runs.batch_statuspolling (hasMore: true→false), andpullBatchFixResultsall completed normally, andbatch_fix_results.jsonwas written and uploaded as an artifact successfully. But the parsed object's.resultskey was missing/null — most likely because the fix engine didn't generate a usable patch for any of the submitted CWE-78 findings, and the API response omitsresultsin that case rather than returning an empty object.Where it breaks
src/create_pr_comment.ts:The same unguarded assumption (
batchFixResults.resultsalways exists) appears in several other places:src/run_batch.ts— thecodeSuggestionblock, andfilterEmptyPatchesFromBatchsrc/checkRun.tssrc/pr_comment_handler.tsAlso, in
run_batch.ts,createPRCommentBatch(batchFixResults, options, flawArray)is called withoutawait. A synchronous throw at the top of that async function therefore becomes an unhandled rejection instead of something the caller can catch — which is why it takes down the whole process instead of failing just that one step gracefully.Suggested fix
Guard each call site for the "batch completed but produced zero usable results" case, e.g.:
and add
awaitbefore thecreatePRCommentBatch(...)call inrun_batch.tsso errors there can't become unhandled rejections.Impact
On a repo where branch protection requires this check to pass, a scan that finds real vulnerabilities but for which the fixer can't generate any patch turns into a hard job/process crash rather than a clean "no auto-fix available" outcome — much worse UX than just reporting zero fixes generated.
Happy to open a PR with the guard clauses if that's useful.