Skip to content

Include stack traces in catchSpectralRunErrors for improved debugging#845

Closed
Copilot wants to merge 8 commits into
mainfrom
copilot/update-error-handling-stack-trace
Closed

Include stack traces in catchSpectralRunErrors for improved debugging#845
Copilot wants to merge 8 commits into
mainfrom
copilot/update-error-handling-stack-trace

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 30, 2026

Summary

Updates catchSpectralRunErrors in spectral-plugin-utils.ts to include stack traces from caught errors. Previously only error messages were logged, which hindered debugging when Spectral validation failures occurred.

Changes

  • Added stack trace output for the top-level caught error (error.stack)
  • Added stack trace output for each constituent error in AggregateError (innerError.stack)
  • Renamed the inner loop variable from error to innerError to avoid shadowing the outer parameter

Security Summary

No security vulnerabilities were introduced or discovered. CodeQL analysis returned zero alerts.

Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
@mikeharder mikeharder marked this pull request as ready for review March 30, 2026 23:28
@mikeharder mikeharder requested a review from Copilot March 30, 2026 23:28
Comment thread packages/azure-openapi-validator/autorest/src/spectral-plugin-utils.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances error reporting in the AutoRest Spectral integration by adding stack traces to the fatal message emitted from catchSpectralRunErrors, improving debuggability when Spectral validation fails.

Changes:

  • Append the top-level caught error’s stack trace to the aggregated error output (when present).
  • Append stack traces for constituent errors when the caught error is an AggregateError-like object.
  • Adjust error-message aggregation logic used to build the fatal output.

Comment on lines 159 to +165
// Initialize an array to collect error messages
const errorMessages: string[] = [error]

if (error && error.stack) {
errorMessages.push(`Stack:\n${error.stack}`)
}

Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorMessages is declared as string[] but initialized with the raw caught error value. Since catch can receive non-Error values (and callers pass unknown), this can produce unhelpful output like [object Object] and makes the array content inconsistent. Consider stringifying the top-level error explicitly (e.g., prefer error.message/String(error)), then optionally append stack traces.

Copilot uses AI. Check for mistakes.
Comment on lines 168 to +172
error.errors.forEach((error: any, index: number) => {
// Push each error message into the array
errorMessages.push(`Error ${index + 1}: ${error.message}`)
if (error.stack) {
errorMessages.push(`Stack ${index + 1}:\n${error.stack}`)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inner forEach callback parameter is still named error, which shadows the outer error parameter and contradicts the intent described in the PR. Rename the inner variable (e.g., innerError) to avoid confusion and make it clear which error’s stack/message is being logged.

Suggested change
error.errors.forEach((error: any, index: number) => {
// Push each error message into the array
errorMessages.push(`Error ${index + 1}: ${error.message}`)
if (error.stack) {
errorMessages.push(`Stack ${index + 1}:\n${error.stack}`)
error.errors.forEach((innerError: any, index: number) => {
// Push each error message into the array
errorMessages.push(`Error ${index + 1}: ${innerError.message}`)
if (innerError.stack) {
errorMessages.push(`Stack ${index + 1}:\n${innerError.stack}`)

Copilot uses AI. Check for mistakes.
Comment on lines 160 to +172
const errorMessages: string[] = [error]

if (error && error.stack) {
errorMessages.push(`Stack:\n${error.stack}`)
}

// Check if "error" contains the "errors" property
if (error && error.errors && Array.isArray(error.errors)) {
error.errors.forEach((error: any, index: number) => {
// Push each error message into the array
errorMessages.push(`Error ${index + 1}: ${error.message}`)
if (error.stack) {
errorMessages.push(`Stack ${index + 1}:\n${error.stack}`)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When formatting constituent AggregateError entries, the code assumes each item has message (and now stack). Since AggregateError.errors can contain arbitrary values, error.message may be undefined and degrade the output. Consider falling back to String(error) when message is missing, and only include a stack trace when it’s a string.

Suggested change
const errorMessages: string[] = [error]
if (error && error.stack) {
errorMessages.push(`Stack:\n${error.stack}`)
}
// Check if "error" contains the "errors" property
if (error && error.errors && Array.isArray(error.errors)) {
error.errors.forEach((error: any, index: number) => {
// Push each error message into the array
errorMessages.push(`Error ${index + 1}: ${error.message}`)
if (error.stack) {
errorMessages.push(`Stack ${index + 1}:\n${error.stack}`)
const errorMessages: string[] = []
// Top-level error message (fall back to String(error) if no .message)
const topLevelMessage =
error && typeof error === "object" && typeof (error as any).message === "string"
? (error as any).message
: String(error)
errorMessages.push(topLevelMessage)
// Top-level stack trace (include only if it's a string)
if (error && typeof (error as any).stack === "string") {
errorMessages.push(`Stack:\n${(error as any).stack}`)
}
// Check if "error" contains the "errors" property (AggregateError)
if (error && Array.isArray((error as any).errors)) {
;(error as any).errors.forEach((innerError: any, index: number) => {
// Derive each constituent error message with a safe fallback
const innerMessage =
innerError && typeof innerError === "object" && typeof innerError.message === "string"
? innerError.message
: String(innerError)
errorMessages.push(`Error ${index + 1}: ${innerMessage}`)
// Include stack trace only when it's a string
if (innerError && typeof innerError.stack === "string") {
errorMessages.push(`Stack ${index + 1}:\n${innerError.stack}`)

Copilot uses AI. Check for mistakes.
@mikeharder
Copy link
Copy Markdown
Member

stack traces were less useful than expected

@mikeharder mikeharder closed this Apr 1, 2026
@mikeharder mikeharder deleted the copilot/update-error-handling-stack-trace branch April 1, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants