Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion scopes/pipelines/builder/task-results-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,34 @@ export class TaskResultsList {

private aggregateTaskErrorsToOneString(componentResult: ComponentResult) {
const rawErrors = componentResult.errors || [];
const errors = rawErrors.map((e) => (typeof e === 'string' ? e : e.toString()));
const errors = rawErrors.map((e) => {
if (typeof e === 'string') {
return e;
}
if (e instanceof Error) {
return e.message;
}
Comment on lines +88 to +90
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

For Error instances, this returns only e.message, so the stack trace is dropped (and the output also loses the error name). This doesn’t match the PR goal of extracting message + stack and makes debugging harder. Consider using e.stack when available (or e.name + e.message plus stack) instead of message-only.

Copilot uses AI. Check for mistakes.
// Handle error objects with message and/or stack properties
if (e && typeof e === 'object') {
const errorObj = e as Record<string, any>;
const hasMessage = 'message' in e && typeof errorObj.message === 'string';
const hasStack = 'stack' in e && typeof errorObj.stack === 'string';
if (hasMessage && hasStack) {
return `${errorObj.message}\n${errorObj.stack}`;
}
if (hasMessage) {
return errorObj.message;
}
if (hasStack) {
return errorObj.stack;
}
}
// Try toString as final fallback
if (typeof (e as any)?.toString === 'function') {
return (e as any).toString();
}
return `unknown error format: ${JSON.stringify(e)}`;
Comment on lines +89 to +110
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

ComponentResult.errors is typed as Array<Error | string> (see scopes/pipelines/builder/types.ts:21), but this function now has runtime handling for non-Error objects (Record<string, any> / 'message' in e). Either widen the errors type to include the supported plain-object shape (or unknown) so callers can legally pass it, or remove this branch to keep the implementation aligned with the public type contract.

Suggested change
return e.message;
}
// Handle error objects with message and/or stack properties
if (e && typeof e === 'object') {
const errorObj = e as Record<string, any>;
const hasMessage = 'message' in e && typeof errorObj.message === 'string';
const hasStack = 'stack' in e && typeof errorObj.stack === 'string';
if (hasMessage && hasStack) {
return `${errorObj.message}\n${errorObj.stack}`;
}
if (hasMessage) {
return errorObj.message;
}
if (hasStack) {
return errorObj.stack;
}
}
// Try toString as final fallback
if (typeof (e as any)?.toString === 'function') {
return (e as any).toString();
}
return `unknown error format: ${JSON.stringify(e)}`;
// Prefer including stack when available for better diagnostics
if (e.stack) {
return `${e.message}\n${e.stack}`;
}
return e.message;
}
// Fallback for unexpected values; should not occur if types are respected
return String(e);

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

JSON.stringify(e) can throw (e.g., circular references) which would cause error formatting itself to crash and potentially mask the original failure. Use a safe stringification (try/catch with a fallback) or a non-throwing formatter like util.inspect for the fallback message.

Copilot uses AI. Check for mistakes.
});
return `component: ${componentResult.component.id.toString()}\n${errors.join('\n')}`;
}

Expand Down
Loading