diff --git a/actions/setup/js/add_comment.cjs b/actions/setup/js/add_comment.cjs
index 80cc9399e6..40b8e25dec 100644
--- a/actions/setup/js/add_comment.cjs
+++ b/actions/setup/js/add_comment.cjs
@@ -6,6 +6,7 @@ const { generateFooterWithMessages } = require("./messages_footer.cjs");
const { getRepositoryUrl } = require("./get_repository_url.cjs");
const { replaceTemporaryIdReferences, loadTemporaryIdMap } = require("./temporary_id.cjs");
const { getTrackerID } = require("./get_tracker_id.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Hide/minimize a comment using the GraphQL API
@@ -314,7 +315,7 @@ async function main() {
core.info(`Allowed reasons for hiding: [${parsed.join(", ")}]`);
return parsed;
} catch (error) {
- core.warning(`Failed to parse GH_AW_ALLOWED_REASONS: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to parse GH_AW_ALLOWED_REASONS: ${getErrorMessage(error)}`);
return null;
}
})()
diff --git a/actions/setup/js/add_copilot_reviewer.cjs b/actions/setup/js/add_copilot_reviewer.cjs
index b82baf2e34..b564663928 100644
--- a/actions/setup/js/add_copilot_reviewer.cjs
+++ b/actions/setup/js/add_copilot_reviewer.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Add Copilot as a reviewer to a pull request.
*
@@ -52,7 +54,7 @@ Successfully added Copilot as a reviewer to PR #${prNumber}.
)
.write();
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to add Copilot as reviewer: ${errorMessage}`);
core.setFailed(`Failed to add Copilot as reviewer to PR #${prNumber}: ${errorMessage}`);
}
diff --git a/actions/setup/js/add_labels.cjs b/actions/setup/js/add_labels.cjs
index cd76c83a5a..3b1d5a851c 100644
--- a/actions/setup/js/add_labels.cjs
+++ b/actions/setup/js/add_labels.cjs
@@ -3,6 +3,7 @@
const { processSafeOutput } = require("./safe_output_processor.cjs");
const { validateLabels } = require("./safe_output_validator.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Use shared processor for common steps
@@ -117,7 +118,7 @@ ${labelsListMarkdown}
)
.write();
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to add labels: ${errorMessage}`);
core.setFailed(`Failed to add labels: ${errorMessage}`);
}
diff --git a/actions/setup/js/add_reaction_and_edit_comment.cjs b/actions/setup/js/add_reaction_and_edit_comment.cjs
index a787b02789..d890d81858 100644
--- a/actions/setup/js/add_reaction_and_edit_comment.cjs
+++ b/actions/setup/js/add_reaction_and_edit_comment.cjs
@@ -2,6 +2,7 @@
///
const { getRunStartedMessage } = require("./messages_run_status.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Read inputs from environment variables
@@ -151,7 +152,7 @@ async function main() {
core.info(`Skipping comment for event type: ${eventName}`);
}
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to process reaction and comment creation: ${errorMessage}`);
core.setFailed(`Failed to process reaction and comment creation: ${errorMessage}`);
}
@@ -457,7 +458,7 @@ async function addCommentWithWorkflowLink(endpoint, runUrl, eventName) {
core.setOutput("comment-repo", `${context.repo.owner}/${context.repo.repo}`);
} catch (error) {
// Don't fail the entire job if comment creation fails - just log it
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.warning("Failed to create comment with workflow link (This is not critical - the reaction was still added successfully): " + errorMessage);
}
}
diff --git a/actions/setup/js/add_reviewer.cjs b/actions/setup/js/add_reviewer.cjs
index 29f59a4021..63a22bfda4 100644
--- a/actions/setup/js/add_reviewer.cjs
+++ b/actions/setup/js/add_reviewer.cjs
@@ -2,6 +2,7 @@
///
const { processSafeOutput, processItems } = require("./safe_output_processor.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
// GitHub Copilot reviewer bot username
const COPILOT_REVIEWER_BOT = "copilot-pull-request-reviewer[bot]";
@@ -125,7 +126,7 @@ ${reviewersListMarkdown}
)
.write();
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to add reviewers: ${errorMessage}`);
core.setFailed(`Failed to add reviewers: ${errorMessage}`);
}
diff --git a/actions/setup/js/assign_agent_helpers.cjs b/actions/setup/js/assign_agent_helpers.cjs
index f8c39d6f47..c939a52cc2 100644
--- a/actions/setup/js/assign_agent_helpers.cjs
+++ b/actions/setup/js/assign_agent_helpers.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Shared helper functions for assigning coding agents (like Copilot) to issues
* These functions use GraphQL to properly assign bot actors that cannot be assigned via gh CLI
@@ -27,6 +29,8 @@ function getAgentName(assignee) {
// Normalize: remove @ prefix if present
const normalized = assignee.startsWith("@") ? assignee.slice(1) : assignee;
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
// Check if it's a known agent
if (AGENT_LOGIN_NAMES[normalized]) {
return normalized;
@@ -118,7 +122,7 @@ async function findAgent(owner, repo, agentName) {
}
return null;
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to find ${agentName} agent: ${errorMessage}`);
return null;
}
@@ -163,7 +167,7 @@ async function getIssueDetails(owner, repo, issueNumber) {
currentAssignees,
};
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to get issue details: ${errorMessage}`);
// Re-throw the error to preserve the original error message for permission error detection
throw error;
@@ -208,7 +212,7 @@ async function assignAgentToIssue(issueId, agentId, currentAssignees, agentName)
core.error("Unexpected response from GitHub API");
return false;
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
// Debug: surface the raw GraphQL error structure for troubleshooting fine-grained permission issues
try {
@@ -400,7 +404,7 @@ async function assignAgentToIssueByName(owner, repo, issueNumber, agentName) {
core.info(`Successfully assigned ${agentName} coding agent to issue #${issueNumber}`);
return { success: true };
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
return { success: false, error: errorMessage };
}
}
diff --git a/actions/setup/js/assign_copilot_to_created_issues.cjs b/actions/setup/js/assign_copilot_to_created_issues.cjs
index e3b4ba604f..0c97669928 100644
--- a/actions/setup/js/assign_copilot_to_created_issues.cjs
+++ b/actions/setup/js/assign_copilot_to_created_issues.cjs
@@ -2,6 +2,7 @@
///
const { AGENT_LOGIN_NAMES, findAgent, getIssueDetails, assignAgentToIssue, generatePermissionErrorSummary } = require("./assign_agent_helpers.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Assign copilot to issues created by create_issue job.
@@ -110,7 +111,7 @@ async function main() {
success: true,
});
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to assign ${agentName} to issue #${issueNumber} in ${repoSlug}: ${errorMessage}`);
results.push({
repo: repoSlug,
diff --git a/actions/setup/js/assign_issue.cjs b/actions/setup/js/assign_issue.cjs
index 44b0150aae..f83e475051 100644
--- a/actions/setup/js/assign_issue.cjs
+++ b/actions/setup/js/assign_issue.cjs
@@ -2,6 +2,7 @@
///
const { getAgentName, getIssueDetails, findAgent, assignAgentToIssue } = require("./assign_agent_helpers.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Assign an issue to a user or bot (including copilot)
@@ -95,7 +96,7 @@ Successfully assigned issue #${trimmedIssueNumber} to \`${trimmedAssignee}\`.
)
.write();
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to assign issue: ${errorMessage}`);
core.setFailed(`Failed to assign issue #${trimmedIssueNumber} to ${trimmedAssignee}: ${errorMessage}`);
}
diff --git a/actions/setup/js/assign_milestone.cjs b/actions/setup/js/assign_milestone.cjs
index 12929fa9d1..0793927a28 100644
--- a/actions/setup/js/assign_milestone.cjs
+++ b/actions/setup/js/assign_milestone.cjs
@@ -2,6 +2,7 @@
///
const { processSafeOutput } = require("./safe_output_processor.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Use shared processor for common steps
@@ -62,7 +63,7 @@ async function main() {
allMilestones = milestonesResponse.data;
core.info(`Fetched ${allMilestones.length} milestones from repository`);
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to fetch milestones: ${errorMessage}`);
core.setFailed(`Failed to fetch milestones for validation: ${errorMessage}`);
return;
@@ -119,7 +120,7 @@ async function main() {
success: true,
});
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to assign milestone #${milestoneNumber} to issue #${issueNumber}: ${errorMessage}`);
results.push({
issue_number: issueNumber,
diff --git a/actions/setup/js/assign_to_agent.cjs b/actions/setup/js/assign_to_agent.cjs
index 1e411abc60..b29a7f5f09 100644
--- a/actions/setup/js/assign_to_agent.cjs
+++ b/actions/setup/js/assign_to_agent.cjs
@@ -4,6 +4,7 @@
const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateStagedPreview } = require("./staged_preview.cjs");
const { AGENT_LOGIN_NAMES, getAvailableAgentLogins, findAgent, getIssueDetails, assignAgentToIssue, generatePermissionErrorSummary } = require("./assign_agent_helpers.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
const result = loadAgentOutput();
@@ -148,7 +149,7 @@ async function main() {
success: true,
});
} catch (error) {
- let errorMessage = error instanceof Error ? error.message : String(error);
+ let errorMessage = getErrorMessage(error);
if (errorMessage.includes("coding agent is not available for this repository")) {
// Enrich with available agent logins to aid troubleshooting - uses built-in github object
try {
diff --git a/actions/setup/js/assign_to_user.cjs b/actions/setup/js/assign_to_user.cjs
index 66241dc016..c53f5fc4f0 100644
--- a/actions/setup/js/assign_to_user.cjs
+++ b/actions/setup/js/assign_to_user.cjs
@@ -2,6 +2,7 @@
///
const { processSafeOutput, processItems } = require("./safe_output_processor.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Use shared processor for common steps
@@ -122,7 +123,7 @@ ${assigneesListMarkdown}
)
.write();
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to assign users: ${errorMessage}`);
core.setFailed(`Failed to assign users: ${errorMessage}`);
}
diff --git a/actions/setup/js/check_command_position.cjs b/actions/setup/js/check_command_position.cjs
index d0df669e00..a7048dd659 100644
--- a/actions/setup/js/check_command_position.cjs
+++ b/actions/setup/js/check_command_position.cjs
@@ -8,6 +8,8 @@
async function main() {
const command = process.env.GH_AW_COMMAND;
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
if (!command) {
core.setFailed("Configuration error: GH_AW_COMMAND not specified.");
return;
@@ -62,7 +64,7 @@ async function main() {
core.setOutput("command_position_ok", "false");
}
} catch (error) {
- core.setFailed(error instanceof Error ? error.message : String(error));
+ core.setFailed(getErrorMessage(error));
}
}
diff --git a/actions/setup/js/check_permissions_utils.cjs b/actions/setup/js/check_permissions_utils.cjs
index 754aa74691..874661d2c7 100644
--- a/actions/setup/js/check_permissions_utils.cjs
+++ b/actions/setup/js/check_permissions_utils.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Shared utility for repository permission validation
* Used by both check_permissions.cjs and check_membership.cjs
@@ -59,14 +61,12 @@ async function checkBotStatus(actor, owner, repo) {
return { isBot: true, isActive: false };
}
// For other errors, we'll treat as inactive to be safe
- // @ts-expect-error - Error handling with optional chaining
- const errorMessage = botError?.message ?? String(botError);
+ const errorMessage = getErrorMessage(botError);
core.warning(`Failed to check bot status: ${errorMessage}`);
return { isBot: true, isActive: false, error: errorMessage };
}
} catch (error) {
- // @ts-expect-error - Error handling with optional chaining
- const errorMessage = error?.message ?? String(error);
+ const errorMessage = getErrorMessage(error);
core.warning(`Error checking bot status: ${errorMessage}`);
return { isBot: false, isActive: false, error: errorMessage };
}
@@ -105,8 +105,7 @@ async function checkRepositoryPermission(actor, owner, repo, requiredPermissions
core.warning(`User permission '${permission}' does not meet requirements: ${requiredPermissions.join(", ")}`);
return { authorized: false, permission };
} catch (repoError) {
- // @ts-expect-error - Error handling with optional chaining
- const errorMessage = repoError?.message ?? String(repoError);
+ const errorMessage = getErrorMessage(repoError);
core.warning(`Repository permission check failed: ${errorMessage}`);
return { authorized: false, error: errorMessage };
}
diff --git a/actions/setup/js/check_skip_if_match.cjs b/actions/setup/js/check_skip_if_match.cjs
index fa8525b928..f54b56875c 100644
--- a/actions/setup/js/check_skip_if_match.cjs
+++ b/actions/setup/js/check_skip_if_match.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
const skipQuery = process.env.GH_AW_SKIP_QUERY;
const workflowName = process.env.GH_AW_WORKFLOW_NAME;
@@ -53,7 +55,7 @@ async function main() {
core.info(`✓ Found ${totalCount} matches (below threshold of ${maxMatches}), workflow can proceed`);
core.setOutput("skip_check_ok", "true");
} catch (error) {
- core.setFailed(`Failed to execute search query: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to execute search query: ${getErrorMessage(error)}`);
return;
}
}
diff --git a/actions/setup/js/check_workflow_timestamp_api.cjs b/actions/setup/js/check_workflow_timestamp_api.cjs
index db00c08a39..277c475fba 100644
--- a/actions/setup/js/check_workflow_timestamp_api.cjs
+++ b/actions/setup/js/check_workflow_timestamp_api.cjs
@@ -7,6 +7,8 @@
* with the compiled .lock.yml file and warns if recompilation is needed
*/
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
const workflowFile = process.env.GH_AW_WORKFLOW_FILE;
@@ -52,7 +54,7 @@ async function main() {
}
return null;
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.info(`Could not fetch commit for ${path}: ${errorMessage}`);
return null;
}
diff --git a/actions/setup/js/checkout_pr_branch.cjs b/actions/setup/js/checkout_pr_branch.cjs
index 86f65dda23..dadf69ad85 100644
--- a/actions/setup/js/checkout_pr_branch.cjs
+++ b/actions/setup/js/checkout_pr_branch.cjs
@@ -6,6 +6,8 @@
* This script handles both pull_request events and comment events on PRs
*/
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
const eventName = context.eventName;
const pullRequest = context.payload.pull_request;
@@ -38,7 +40,7 @@ async function main() {
core.info(`✅ Successfully checked out PR #${prNumber}`);
}
} catch (error) {
- core.setFailed(`Failed to checkout PR branch: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to checkout PR branch: ${getErrorMessage(error)}`);
}
}
diff --git a/actions/setup/js/checkout_pr_branch.test.cjs b/actions/setup/js/checkout_pr_branch.test.cjs
index b033fd1875..af9958e4fc 100644
--- a/actions/setup/js/checkout_pr_branch.test.cjs
+++ b/actions/setup/js/checkout_pr_branch.test.cjs
@@ -53,12 +53,20 @@ describe("checkout_pr_branch.cjs", () => {
const scriptPath = path.join(import.meta.dirname, "checkout_pr_branch.cjs");
const scriptContent = fs.readFileSync(scriptPath, "utf8");
+ // Mock require for the script
+ const mockRequire = module => {
+ if (module === "./error_helpers.cjs") {
+ return { getErrorMessage: error => (error instanceof Error ? error.message : String(error)) };
+ }
+ throw new Error(`Module ${module} not mocked in test`);
+ };
+
// Execute the script in a new context with our mocks
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
- const wrappedScript = new AsyncFunction("core", "exec", "context", scriptContent.replace(/module\.exports = \{ main \};?\s*$/s, "await main();"));
+ const wrappedScript = new AsyncFunction("core", "exec", "context", "require", scriptContent.replace(/module\.exports = \{ main \};?\s*$/s, "await main();"));
try {
- await wrappedScript(mockCore, mockExec, mockContext);
+ await wrappedScript(mockCore, mockExec, mockContext, mockRequire);
} catch (error) {
// Errors are handled by the script itself via core.setFailed
}
diff --git a/actions/setup/js/close_discussion.cjs b/actions/setup/js/close_discussion.cjs
index 5db69bea76..fad827c3b0 100644
--- a/actions/setup/js/close_discussion.cjs
+++ b/actions/setup/js/close_discussion.cjs
@@ -5,6 +5,7 @@ const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateFooter } = require("./generate_footer.cjs");
const { getTrackerID } = require("./get_tracker_id.cjs");
const { getRepositoryUrl } = require("./get_repository_url.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Get discussion details using GraphQL
@@ -294,7 +295,7 @@ async function main() {
core.setOutput("comment_url", comment.url);
}
} catch (error) {
- core.error(`✗ Failed to close discussion #${discussionNumber}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to close discussion #${discussionNumber}: ${getErrorMessage(error)}`);
throw error;
}
}
diff --git a/actions/setup/js/close_entity_helpers.cjs b/actions/setup/js/close_entity_helpers.cjs
index 08797458c5..fc3d2d5691 100644
--- a/actions/setup/js/close_entity_helpers.cjs
+++ b/actions/setup/js/close_entity_helpers.cjs
@@ -5,6 +5,7 @@ const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateFooter } = require("./generate_footer.cjs");
const { getTrackerID } = require("./get_tracker_id.cjs");
const { getRepositoryUrl } = require("./get_repository_url.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* @typedef {'issue' | 'pull_request'} EntityType
@@ -324,7 +325,7 @@ async function processCloseEntityItems(config, callbacks) {
core.setOutput("comment_url", comment.html_url);
}
} catch (error) {
- core.error(`✗ Failed to close ${config.displayName} #${entityNumber}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to close ${config.displayName} #${entityNumber}: ${getErrorMessage(error)}`);
throw error;
}
}
diff --git a/actions/setup/js/close_expired_discussions.cjs b/actions/setup/js/close_expired_discussions.cjs
index 0cd3db2dec..c9e4035d29 100644
--- a/actions/setup/js/close_expired_discussions.cjs
+++ b/actions/setup/js/close_expired_discussions.cjs
@@ -1,6 +1,8 @@
// @ts-check
//
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Maximum number of discussions to update per run
*/
@@ -32,6 +34,8 @@ async function searchDiscussionsWithExpiration(github, owner, repo) {
let hasNextPage = true;
let cursor = null;
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
while (hasNextPage) {
const query = `
query($owner: String!, $repo: String!, $cursor: String) {
@@ -256,7 +260,7 @@ async function main() {
closedCount++;
core.info(`✓ Closed discussion #${discussion.number}: ${discussion.url}`);
} catch (error) {
- core.error(`✗ Failed to close discussion #${discussion.number}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to close discussion #${discussion.number}: ${getErrorMessage(error)}`);
// Continue with other discussions even if one fails
}
diff --git a/actions/setup/js/close_expired_issues.cjs b/actions/setup/js/close_expired_issues.cjs
index 63436f3668..d36c85ea47 100644
--- a/actions/setup/js/close_expired_issues.cjs
+++ b/actions/setup/js/close_expired_issues.cjs
@@ -1,6 +1,8 @@
// @ts-check
//
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Maximum number of issues to update per run
*/
@@ -32,6 +34,8 @@ async function searchIssuesWithExpiration(github, owner, repo) {
let hasNextPage = true;
let cursor = null;
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
while (hasNextPage) {
const query = `
query($owner: String!, $repo: String!, $cursor: String) {
@@ -249,7 +253,7 @@ async function main() {
closedCount++;
core.info(`✓ Closed issue #${issue.number}: ${issue.url}`);
} catch (error) {
- core.error(`✗ Failed to close issue #${issue.number}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to close issue #${issue.number}: ${getErrorMessage(error)}`);
// Continue with other issues even if one fails
}
diff --git a/actions/setup/js/close_older_discussions.cjs b/actions/setup/js/close_older_discussions.cjs
index b5aeda6a73..c2ab8a97d4 100644
--- a/actions/setup/js/close_older_discussions.cjs
+++ b/actions/setup/js/close_older_discussions.cjs
@@ -2,6 +2,7 @@
///
const { getCloseOlderDiscussionMessage } = require("./messages_close_discussion.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Maximum number of older discussions to close
@@ -242,7 +243,7 @@ async function closeOlderDiscussions(github, owner, repo, titlePrefix, labels, c
core.info(`✓ Closed discussion #${discussion.number}: ${discussion.url}`);
} catch (error) {
- core.error(`✗ Failed to close discussion #${discussion.number}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to close discussion #${discussion.number}: ${getErrorMessage(error)}`);
// Continue with other discussions even if one fails
}
diff --git a/actions/setup/js/collect_ndjson_output.cjs b/actions/setup/js/collect_ndjson_output.cjs
index d53305392f..60756ca8c7 100644
--- a/actions/setup/js/collect_ndjson_output.cjs
+++ b/actions/setup/js/collect_ndjson_output.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
const fs = require("fs");
const { sanitizeContent } = require("./sanitize_content.cjs");
@@ -19,7 +21,7 @@ async function main() {
core.info(`Loaded validation config from ${validationConfigPath}`);
}
} catch (error) {
- core.warning(`Failed to read validation config from ${validationConfigPath}: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to read validation config from ${validationConfigPath}: ${getErrorMessage(error)}`);
}
// Extract mentions configuration from validation config
@@ -187,7 +189,7 @@ async function main() {
core.info(`[INGESTION] Config file does not exist at: ${configPath}`);
}
} catch (error) {
- core.warning(`Failed to read config file from ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to read config file from ${configPath}: ${getErrorMessage(error)}`);
}
core.info(`[INGESTION] Output file path: ${outputFile}`);
@@ -217,7 +219,7 @@ async function main() {
core.info(`[INGESTION] Expected output types after normalization: ${JSON.stringify(Object.keys(expectedOutputTypes))}`);
core.info(`[INGESTION] Expected output types full config: ${JSON.stringify(expectedOutputTypes)}`);
} catch (error) {
- const errorMsg = error instanceof Error ? error.message : String(error);
+ const errorMsg = getErrorMessage(error);
core.info(`Warning: Could not parse safe-outputs config: ${errorMsg}`);
}
}
@@ -292,7 +294,7 @@ async function main() {
core.info(`Line ${i + 1}: Valid ${itemType} item`);
parsedItems.push(item);
} catch (error) {
- const errorMsg = error instanceof Error ? error.message : String(error);
+ const errorMsg = getErrorMessage(error);
errors.push(`Line ${i + 1}: Invalid JSON - ${errorMsg}`);
}
}
@@ -322,7 +324,7 @@ async function main() {
core.info(`Stored validated output to: ${agentOutputFile}`);
core.exportVariable("GH_AW_AGENT_OUTPUT", agentOutputFile);
} catch (error) {
- const errorMsg = error instanceof Error ? error.message : String(error);
+ const errorMsg = getErrorMessage(error);
core.error(`Failed to write agent output file: ${errorMsg}`);
}
core.setOutput("output", JSON.stringify(validatedOutput));
diff --git a/actions/setup/js/compute_text.cjs b/actions/setup/js/compute_text.cjs
index d4f77620d6..19560baaf1 100644
--- a/actions/setup/js/compute_text.cjs
+++ b/actions/setup/js/compute_text.cjs
@@ -7,6 +7,7 @@
* @returns {string} The sanitized content
*/
const { sanitizeIncomingText, writeRedactedDomainsLog } = require("./sanitize_incoming_text.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
let text = "";
@@ -125,7 +126,7 @@ async function main() {
const body = release.body || "";
text = `${name}\n\n${body}`;
} catch (error) {
- core.warning(`Failed to fetch release from URL: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to fetch release from URL: ${getErrorMessage(error)}`);
}
}
} else if (releaseId) {
@@ -140,7 +141,7 @@ async function main() {
const body = release.body || "";
text = `${name}\n\n${body}`;
} catch (error) {
- core.warning(`Failed to fetch release by ID: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to fetch release by ID: ${getErrorMessage(error)}`);
}
}
}
diff --git a/actions/setup/js/create_agent_task.cjs b/actions/setup/js/create_agent_task.cjs
index f6f50f08c8..a8641e0bcd 100644
--- a/actions/setup/js/create_agent_task.cjs
+++ b/actions/setup/js/create_agent_task.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
const path = require("path");
@@ -21,7 +23,7 @@ async function main() {
try {
outputContent = fs.readFileSync(agentOutputFile, "utf8");
} catch (error) {
- core.setFailed(`Error reading agent output file: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error reading agent output file: ${getErrorMessage(error)}`);
return;
}
@@ -35,7 +37,7 @@ async function main() {
try {
validatedOutput = JSON.parse(outputContent);
} catch (error) {
- core.setFailed(`Error parsing agent output JSON: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error parsing agent output JSON: ${getErrorMessage(error)}`);
return;
}
@@ -155,7 +157,7 @@ async function main() {
createdTasks.push({ number: "", url: output });
}
} catch (error) {
- core.error(`Task ${index + 1}: Error creating agent task: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`Task ${index + 1}: Error creating agent task: ${getErrorMessage(error)}`);
}
}
diff --git a/actions/setup/js/create_code_scanning_alert.cjs b/actions/setup/js/create_code_scanning_alert.cjs
index bd70bc892e..8f2cf287f6 100644
--- a/actions/setup/js/create_code_scanning_alert.cjs
+++ b/actions/setup/js/create_code_scanning_alert.cjs
@@ -2,6 +2,7 @@
///
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
const result = loadAgentOutput();
@@ -230,7 +231,7 @@ async function main() {
await core.summary.addRaw(summaryContent).write();
} catch (error) {
- core.error(`✗ Failed to create SARIF file: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to create SARIF file: ${getErrorMessage(error)}`);
throw error;
}
diff --git a/actions/setup/js/create_discussion.cjs b/actions/setup/js/create_discussion.cjs
index 066bd6aa04..65c35ff07e 100644
--- a/actions/setup/js/create_discussion.cjs
+++ b/actions/setup/js/create_discussion.cjs
@@ -8,6 +8,7 @@ const { replaceTemporaryIdReferences, loadTemporaryIdMap } = require("./temporar
const { parseAllowedRepos, getDefaultTargetRepo, validateRepo, parseRepoSlug } = require("./repo_helpers.cjs");
const { addExpirationComment } = require("./expiration_helpers.cjs");
const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Fetch repository ID and discussion categories for a repository
@@ -196,7 +197,7 @@ async function main() {
repoInfoCache.set(itemRepo, repoInfo);
core.info(`Fetched discussion categories for ${itemRepo}: ${JSON.stringify(repoInfo.discussionCategories.map(cat => ({ name: cat.name, id: cat.id })))}`);
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
if (errorMessage.includes("Not Found") || errorMessage.includes("not found") || errorMessage.includes("Could not resolve to a Repository")) {
core.warning(`Skipping discussion: Discussions are not enabled for repository '${itemRepo}'`);
continue;
@@ -319,7 +320,7 @@ async function main() {
core.warning("close-older-discussions is enabled but no title-prefix or labels are set - skipping close older discussions");
}
} catch (error) {
- core.error(`✗ Failed to create discussion "${title}" in ${itemRepo}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to create discussion "${title}" in ${itemRepo}: ${getErrorMessage(error)}`);
throw error;
}
}
diff --git a/actions/setup/js/create_issue.cjs b/actions/setup/js/create_issue.cjs
index eaf53c1a03..e4e0ca0aa4 100644
--- a/actions/setup/js/create_issue.cjs
+++ b/actions/setup/js/create_issue.cjs
@@ -10,6 +10,7 @@ const { generateTemporaryId, isTemporaryId, normalizeTemporaryId, replaceTempora
const { parseAllowedRepos, getDefaultTargetRepo, validateRepo, parseRepoSlug } = require("./repo_helpers.cjs");
const { addExpirationComment } = require("./expiration_helpers.cjs");
const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Initialize outputs to empty strings to ensure they're always set
@@ -287,7 +288,7 @@ async function main() {
core.info("✓ Successfully linked issue #" + issue.number + " as sub-issue of #" + effectiveParentIssueNumber);
} catch (error) {
- core.info(`Warning: Could not link sub-issue to parent: ${error instanceof Error ? error.message : String(error)}`);
+ core.info(`Warning: Could not link sub-issue to parent: ${getErrorMessage(error)}`);
core.info(`Error details: ${error instanceof Error ? error.stack : String(error)}`);
// Fallback: add a comment if sub-issue linking fails
try {
@@ -313,7 +314,7 @@ async function main() {
core.setOutput("issue_url", issue.html_url);
}
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
if (errorMessage.includes("Issues has been disabled in this repository")) {
core.info(`⚠ Cannot create issue "${title}" in ${itemRepo}: Issues are disabled for this repository`);
core.info("Consider enabling issues in repository settings if you want to create issues automatically");
diff --git a/actions/setup/js/create_pr_review_comment.cjs b/actions/setup/js/create_pr_review_comment.cjs
index 65f6d6cb48..3e0abdb6d4 100644
--- a/actions/setup/js/create_pr_review_comment.cjs
+++ b/actions/setup/js/create_pr_review_comment.cjs
@@ -5,6 +5,7 @@ const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateStagedPreview } = require("./staged_preview.cjs");
const { generateFooter } = require("./generate_footer.cjs");
const { getRepositoryUrl } = require("./get_repository_url.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Check if we're in staged mode
@@ -155,7 +156,7 @@ async function main() {
pullRequest = fullPR;
core.info(`Fetched full pull request details for PR #${pullRequestNumber}`);
} catch (error) {
- core.info(`Failed to fetch pull request details for PR #${pullRequestNumber}: ${error instanceof Error ? error.message : String(error)}`);
+ core.info(`Failed to fetch pull request details for PR #${pullRequestNumber}: ${getErrorMessage(error)}`);
continue;
}
}
@@ -238,7 +239,7 @@ async function main() {
core.setOutput("review_comment_url", comment.html_url);
}
} catch (error) {
- core.error(`✗ Failed to create review comment: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to create review comment: ${getErrorMessage(error)}`);
throw error;
}
}
diff --git a/actions/setup/js/create_pull_request.cjs b/actions/setup/js/create_pull_request.cjs
index 7436d2ce43..01e3e4f561 100644
--- a/actions/setup/js/create_pull_request.cjs
+++ b/actions/setup/js/create_pull_request.cjs
@@ -9,6 +9,7 @@ const { updateActivationComment } = require("./update_activation_comment.cjs");
const { getTrackerID } = require("./get_tracker_id.cjs");
const { addExpirationComment } = require("./expiration_helpers.cjs");
const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Generate a patch preview with max 500 lines and 2000 chars for issue body
@@ -71,7 +72,7 @@ async function main() {
try {
outputContent = fs.readFileSync(agentOutputFile, "utf8");
} catch (error) {
- core.setFailed(`Error reading agent output file: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error reading agent output file: ${getErrorMessage(error)}`);
return;
}
}
@@ -224,7 +225,7 @@ async function main() {
try {
validatedOutput = JSON.parse(outputContent);
} catch (error) {
- core.setFailed(`Error parsing agent output JSON: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error parsing agent output JSON: ${getErrorMessage(error)}`);
return;
}
diff --git a/actions/setup/js/create_pull_request.test.cjs b/actions/setup/js/create_pull_request.test.cjs
index 1fae264f1b..9e81eb56b8 100644
--- a/actions/setup/js/create_pull_request.test.cjs
+++ b/actions/setup/js/create_pull_request.test.cjs
@@ -13,8 +13,9 @@ const createTestableFunction = scriptContent => {
(scriptBody = scriptBody.replace(/const \{ getTrackerID \} = require\("\.\/get_tracker_id\.cjs"\);?\s*/g, "")),
(scriptBody = scriptBody.replace(/const \{ addExpirationComment \} = require\("\.\/expiration_helpers\.cjs"\);?\s*/g, "")),
(scriptBody = scriptBody.replace(/const \{ removeDuplicateTitleFromDescription \} = require\("\.\/remove_duplicate_title\.cjs"\);?\s*/g, "")),
+ (scriptBody = scriptBody.replace(/const \{ getErrorMessage \} = require\("\.\/error_helpers\.cjs"\);?\s*/g, "")),
new Function(
- `\n const { fs, crypto, github, core, context, process, console, updateActivationComment, getTrackerID, addExpirationComment, removeDuplicateTitleFromDescription } = arguments[0];\n \n ${scriptBody}\n \n return main;\n `
+ `\n const { fs, crypto, github, core, context, process, console, updateActivationComment, getTrackerID, addExpirationComment, removeDuplicateTitleFromDescription, getErrorMessage } = arguments[0];\n \n ${scriptBody}\n \n return main;\n `
)
);
};
@@ -71,6 +72,7 @@ describe("create_pull_request.cjs", () => {
getTrackerID: vi.fn(format => ""),
addExpirationComment: vi.fn(),
removeDuplicateTitleFromDescription: vi.fn((title, description) => description),
+ getErrorMessage: vi.fn(error => (error instanceof Error ? error.message : String(error))),
}));
}),
afterEach(() => {
diff --git a/actions/setup/js/generate_git_patch.cjs b/actions/setup/js/generate_git_patch.cjs
index af9654f28f..552e59311f 100644
--- a/actions/setup/js/generate_git_patch.cjs
+++ b/actions/setup/js/generate_git_patch.cjs
@@ -6,6 +6,7 @@ const path = require("path");
const { execSync } = require("child_process");
const { getBaseBranch } = require("./get_base_branch.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Generates a git patch file for the current changes
@@ -100,7 +101,7 @@ function generateGitPatch(branchName) {
}
}
} catch (error) {
- errorMessage = `Failed to generate patch: ${error instanceof Error ? error.message : String(error)}`;
+ errorMessage = `Failed to generate patch: ${getErrorMessage(error)}`;
}
// Check if patch was generated and has content
diff --git a/actions/setup/js/hide_comment.cjs b/actions/setup/js/hide_comment.cjs
index c63dbf1291..4e863422af 100644
--- a/actions/setup/js/hide_comment.cjs
+++ b/actions/setup/js/hide_comment.cjs
@@ -2,6 +2,7 @@
///
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Hide a comment using the GraphQL API.
@@ -40,7 +41,7 @@ async function main() {
allowedReasons = JSON.parse(process.env.GH_AW_HIDE_COMMENT_ALLOWED_REASONS);
core.info(`Allowed reasons for hiding: [${allowedReasons.join(", ")}]`);
} catch (error) {
- core.warning(`Failed to parse GH_AW_HIDE_COMMENT_ALLOWED_REASONS: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to parse GH_AW_HIDE_COMMENT_ALLOWED_REASONS: ${getErrorMessage(error)}`);
}
}
@@ -110,7 +111,7 @@ async function main() {
throw new Error(`Failed to hide comment: ${commentId}`);
}
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to hide comment: ${errorMessage}`);
core.setFailed(`Failed to hide comment: ${errorMessage}`);
return;
diff --git a/actions/setup/js/interpolate_prompt.cjs b/actions/setup/js/interpolate_prompt.cjs
index aa34145996..6a8fa84eeb 100644
--- a/actions/setup/js/interpolate_prompt.cjs
+++ b/actions/setup/js/interpolate_prompt.cjs
@@ -8,6 +8,7 @@
const fs = require("fs");
const { isTruthy } = require("./is_truthy.cjs");
const { processRuntimeImports } = require("./runtime_import.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Interpolates variables in the prompt content
@@ -119,7 +120,7 @@ async function main() {
// Write back to the same file
fs.writeFileSync(promptPath, content, "utf8");
} catch (error) {
- core.setFailed(error instanceof Error ? error.message : String(error));
+ core.setFailed(getErrorMessage(error));
}
}
diff --git a/actions/setup/js/link_sub_issue.cjs b/actions/setup/js/link_sub_issue.cjs
index dc90c83955..7fadeeb367 100644
--- a/actions/setup/js/link_sub_issue.cjs
+++ b/actions/setup/js/link_sub_issue.cjs
@@ -4,6 +4,7 @@
const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateStagedPreview } = require("./staged_preview.cjs");
const { loadTemporaryIdMap, resolveIssueNumber } = require("./temporary_id.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
const result = loadAgentOutput();
@@ -164,7 +165,7 @@ async function main() {
});
parentIssue = parentResponse.data;
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.warning(`Failed to fetch parent issue #${parentIssueNumber}: ${errorMessage}`);
results.push({
parent_issue_number: parentIssueNumber,
@@ -212,7 +213,7 @@ async function main() {
});
subIssue = subResponse.data;
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to fetch sub-issue #${subIssueNumber}: ${errorMessage}`);
results.push({
parent_issue_number: parentIssueNumber,
@@ -256,7 +257,7 @@ async function main() {
}
} catch (error) {
// If the GraphQL query fails (e.g., parent field not available), log warning but continue
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.warning(`Could not check if sub-issue #${subIssueNumber} has a parent: ${errorMessage}. Proceeding with link attempt.`);
}
@@ -322,7 +323,7 @@ async function main() {
success: true,
});
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.warning(`Failed to link issue #${subIssueNumber} as sub-issue of #${parentIssueNumber}: ${errorMessage}`);
results.push({
parent_issue_number: parentIssueNumber,
diff --git a/actions/setup/js/load_agent_output.cjs b/actions/setup/js/load_agent_output.cjs
index caaa944e6c..0863647df3 100644
--- a/actions/setup/js/load_agent_output.cjs
+++ b/actions/setup/js/load_agent_output.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
/**
@@ -53,7 +55,7 @@ function loadAgentOutput() {
try {
outputContent = fs.readFileSync(agentOutputFile, "utf8");
} catch (error) {
- const errorMessage = `Error reading agent output file: ${error instanceof Error ? error.message : String(error)}`;
+ const errorMessage = `Error reading agent output file: ${getErrorMessage(error)}`;
core.error(errorMessage);
return { success: false, error: errorMessage };
}
@@ -71,7 +73,7 @@ function loadAgentOutput() {
try {
validatedOutput = JSON.parse(outputContent);
} catch (error) {
- const errorMessage = `Error parsing agent output JSON: ${error instanceof Error ? error.message : String(error)}`;
+ const errorMessage = `Error parsing agent output JSON: ${getErrorMessage(error)}`;
core.error(errorMessage);
core.info(`Failed to parse content:\n${truncateForLogging(outputContent)}`);
return { success: false, error: errorMessage };
diff --git a/actions/setup/js/lock-issue.cjs b/actions/setup/js/lock-issue.cjs
index 0e26b67b8e..dae96e3395 100644
--- a/actions/setup/js/lock-issue.cjs
+++ b/actions/setup/js/lock-issue.cjs
@@ -7,6 +7,8 @@
* to prevent concurrent modifications during agent workflow execution
*/
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
// Log actor and event information for debugging
core.info(`Lock-issue debug: actor=${context.actor}, eventName=${context.eventName}`);
@@ -59,7 +61,7 @@ async function main() {
// Set output to indicate the issue was locked and needs to be unlocked
core.setOutput("locked", "true");
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to lock issue: ${errorMessage}`);
core.setFailed(`Failed to lock issue #${issueNumber}: ${errorMessage}`);
core.setOutput("locked", "false");
diff --git a/actions/setup/js/log_parser_bootstrap.cjs b/actions/setup/js/log_parser_bootstrap.cjs
index 19e63632e7..e936152ca1 100644
--- a/actions/setup/js/log_parser_bootstrap.cjs
+++ b/actions/setup/js/log_parser_bootstrap.cjs
@@ -2,6 +2,7 @@
///
const { generatePlainTextSummary, generateCopilotCliStyleSummary, formatSafeOutputsPreview } = require("./log_parser_shared.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Bootstrap helper for log parser entry points.
@@ -95,7 +96,7 @@ function runLogParser(options) {
try {
safeOutputsContent = fs.readFileSync(safeOutputsPath, "utf8");
} catch (error) {
- core.warning(`Failed to read safe outputs file: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to read safe outputs file: ${getErrorMessage(error)}`);
}
}
diff --git a/actions/setup/js/log_parser_shared.cjs b/actions/setup/js/log_parser_shared.cjs
index 7e14ca20e7..5ce12983c7 100644
--- a/actions/setup/js/log_parser_shared.cjs
+++ b/actions/setup/js/log_parser_shared.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Shared utility functions for log parsers
* Used by parse_claude_log.cjs, parse_copilot_log.cjs, and parse_codex_log.cjs
@@ -1495,7 +1497,7 @@ function wrapLogParser(parseFunction, parserName, logContent) {
try {
return parseFunction(logContent);
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
return {
markdown: `## Agent Log Summary\n\nError parsing ${parserName} log (tried both JSON array and JSONL formats): ${errorMessage}\n`,
mcpFailures: [],
diff --git a/actions/setup/js/mcp_logger.cjs b/actions/setup/js/mcp_logger.cjs
index c4e764160a..aa152e01c6 100644
--- a/actions/setup/js/mcp_logger.cjs
+++ b/actions/setup/js/mcp_logger.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* MCP Logger Utility
*
@@ -37,7 +39,7 @@ function createLogger(serverName) {
* @param {Error|string|any} error - Error object or message
*/
debugError: (prefix, error) => {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
logger.debug(`${prefix}${errorMessage}`);
if (error instanceof Error && error.stack) {
logger.debug(`${prefix}Stack trace: ${error.stack}`);
diff --git a/actions/setup/js/mcp_server_core.cjs b/actions/setup/js/mcp_server_core.cjs
index a751085bc7..9402c0d577 100644
--- a/actions/setup/js/mcp_server_core.cjs
+++ b/actions/setup/js/mcp_server_core.cjs
@@ -25,6 +25,7 @@ const path = require("path");
const { ReadBuffer } = require("./read_buffer.cjs");
const { validateRequiredFields } = require("./safe_inputs_validation.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
const { generateEnhancedErrorMessage } = require("./mcp_enhanced_errors.cjs");
const encoder = new TextEncoder();
@@ -115,7 +116,7 @@ function createDebugFunction(server) {
*/
function createDebugErrorFunction(server) {
return (prefix, error) => {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
server.debug(`${prefix}${errorMessage}`);
if (error instanceof Error && error.stack) {
server.debug(`${prefix}Stack trace: ${error.stack}`);
@@ -704,7 +705,7 @@ async function processReadBuffer(server, defaultHandler) {
} catch (error) {
// For parse errors, we can't know the request id, so we shouldn't send a response
// according to JSON-RPC spec. Just log the error.
- server.debug(`Parse error: ${error instanceof Error ? error.message : String(error)}`);
+ server.debug(`Parse error: ${getErrorMessage(error)}`);
}
}
}
diff --git a/actions/setup/js/messages_core.cjs b/actions/setup/js/messages_core.cjs
index ce38d3afed..fc66063ce5 100644
--- a/actions/setup/js/messages_core.cjs
+++ b/actions/setup/js/messages_core.cjs
@@ -43,11 +43,13 @@ function getMessages() {
return null;
}
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
try {
// Parse JSON with camelCase keys from Go struct (using json struct tags)
return JSON.parse(messagesEnv);
} catch (error) {
- core.warning(`Failed to parse GH_AW_SAFE_OUTPUT_MESSAGES: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to parse GH_AW_SAFE_OUTPUT_MESSAGES: ${getErrorMessage(error)}`);
return null;
}
}
diff --git a/actions/setup/js/missing_tool.cjs b/actions/setup/js/missing_tool.cjs
index a566dccfbc..68c65c5398 100644
--- a/actions/setup/js/missing_tool.cjs
+++ b/actions/setup/js/missing_tool.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
const fs = require("fs");
@@ -29,7 +31,7 @@ async function main() {
try {
agentOutput = fs.readFileSync(agentOutputFile, "utf8");
} catch (error) {
- core.info(`Agent output file not found or unreadable: ${error instanceof Error ? error.message : String(error)}`);
+ core.info(`Agent output file not found or unreadable: ${getErrorMessage(error)}`);
core.setOutput("tools_reported", JSON.stringify(missingTools));
core.setOutput("total_count", missingTools.length.toString());
return;
@@ -49,7 +51,7 @@ async function main() {
try {
validatedOutput = JSON.parse(agentOutput);
} catch (error) {
- core.setFailed(`Error parsing agent output JSON: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error parsing agent output JSON: ${getErrorMessage(error)}`);
return;
}
diff --git a/actions/setup/js/missing_tool.test.cjs b/actions/setup/js/missing_tool.test.cjs
index 655ea17d34..86f1bfda3a 100644
--- a/actions/setup/js/missing_tool.test.cjs
+++ b/actions/setup/js/missing_tool.test.cjs
@@ -43,6 +43,7 @@ describe("missing_tool.cjs", () => {
(global.require = vi.fn().mockImplementation(module => {
if ("fs" === module) return fs;
if ("@actions/core" === module) return mockCore;
+ if ("./error_helpers.cjs" === module) return { getErrorMessage: error => (error instanceof Error ? error.message : String(error)) };
throw new Error(`Module not found: ${module}`);
})));
const scriptPath = path.join(__dirname, "missing_tool.cjs");
diff --git a/actions/setup/js/notify_comment_error.cjs b/actions/setup/js/notify_comment_error.cjs
index 93a371a3d8..0659326c32 100644
--- a/actions/setup/js/notify_comment_error.cjs
+++ b/actions/setup/js/notify_comment_error.cjs
@@ -7,6 +7,7 @@
const { loadAgentOutput } = require("./load_agent_output.cjs");
const { getRunSuccessMessage, getRunFailureMessage, getDetectionFailureMessage } = require("./messages_run_status.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Collect generated asset URLs from safe output jobs
@@ -25,7 +26,7 @@ function collectGeneratedAssets() {
try {
jobOutputMapping = JSON.parse(safeOutputJobsEnv);
} catch (error) {
- core.warning(`Failed to parse GH_AW_SAFE_OUTPUT_JOBS: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to parse GH_AW_SAFE_OUTPUT_JOBS: ${getErrorMessage(error)}`);
return assets;
}
@@ -203,7 +204,7 @@ async function main() {
}
} catch (error) {
// Don't fail the workflow if we can't update the comment
- core.warning(`Failed to update comment: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to update comment: ${getErrorMessage(error)}`);
}
}
diff --git a/actions/setup/js/parse_safe_inputs_logs.cjs b/actions/setup/js/parse_safe_inputs_logs.cjs
index 43bea2773c..6c9691c3a0 100644
--- a/actions/setup/js/parse_safe_inputs_logs.cjs
+++ b/actions/setup/js/parse_safe_inputs_logs.cjs
@@ -13,6 +13,8 @@ async function main() {
const fs = require("fs");
const path = require("path");
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
try {
// Get the safe-inputs logs directory path
const safeInputsLogsDir = `/tmp/gh-aw/safe-inputs/logs/`;
@@ -63,7 +65,7 @@ async function main() {
const summary = generateSafeInputsSummary(allLogEntries);
core.summary.addRaw(summary).write();
} catch (error) {
- core.setFailed(error instanceof Error ? error.message : String(error));
+ core.setFailed(getErrorMessage(error));
}
}
diff --git a/actions/setup/js/push_repo_memory.cjs b/actions/setup/js/push_repo_memory.cjs
index 23318e27fd..c9e026c48f 100644
--- a/actions/setup/js/push_repo_memory.cjs
+++ b/actions/setup/js/push_repo_memory.cjs
@@ -4,6 +4,7 @@
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Push repo-memory changes to git branch
@@ -201,7 +202,7 @@ async function main() {
core.info(`Created orphan branch: ${branchName}`);
}
} catch (error) {
- core.setFailed(`Failed to checkout branch: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to checkout branch: ${getErrorMessage(error)}`);
return;
}
@@ -290,7 +291,7 @@ async function main() {
try {
scanDirectory(sourceMemoryPath);
} catch (error) {
- core.setFailed(`Failed to scan artifact directory: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to scan artifact directory: ${getErrorMessage(error)}`);
return;
}
@@ -344,7 +345,7 @@ async function main() {
fs.copyFileSync(file.source, destFilePath);
core.info(`Copied: ${file.relativePath} (${file.size} bytes)`);
} catch (error) {
- core.setFailed(`Failed to copy file ${file.relativePath}: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to copy file ${file.relativePath}: ${getErrorMessage(error)}`);
return;
}
}
@@ -355,7 +356,7 @@ async function main() {
const status = execSync("git status --porcelain", { encoding: "utf8" });
hasChanges = status.trim().length > 0;
} catch (error) {
- core.setFailed(`Failed to check git status: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to check git status: ${getErrorMessage(error)}`);
return;
}
@@ -370,7 +371,7 @@ async function main() {
try {
execSync("git add .", { stdio: "inherit" });
} catch (error) {
- core.setFailed(`Failed to stage changes: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to stage changes: ${getErrorMessage(error)}`);
return;
}
@@ -378,7 +379,7 @@ async function main() {
try {
execSync(`git commit -m "Update repo memory from workflow run ${githubRunId}"`, { stdio: "inherit" });
} catch (error) {
- core.setFailed(`Failed to commit changes: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to commit changes: ${getErrorMessage(error)}`);
return;
}
@@ -389,7 +390,7 @@ async function main() {
execSync(`git pull --no-rebase -X ours "${repoUrl}" "${branchName}"`, { stdio: "inherit" });
} catch (error) {
// Pull might fail if branch doesn't exist yet or on conflicts - this is acceptable
- core.warning(`Pull failed (this may be expected): ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Pull failed (this may be expected): ${getErrorMessage(error)}`);
}
// Push changes
@@ -399,7 +400,7 @@ async function main() {
execSync(`git push "${repoUrl}" HEAD:"${branchName}"`, { stdio: "inherit" });
core.info(`Successfully pushed changes to ${branchName} branch`);
} catch (error) {
- core.setFailed(`Failed to push changes: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to push changes: ${getErrorMessage(error)}`);
return;
}
}
diff --git a/actions/setup/js/push_to_pull_request_branch.cjs b/actions/setup/js/push_to_pull_request_branch.cjs
index 25ffcc183a..16f50bb11e 100644
--- a/actions/setup/js/push_to_pull_request_branch.cjs
+++ b/actions/setup/js/push_to_pull_request_branch.cjs
@@ -5,6 +5,7 @@
const fs = require("fs");
const { generateStagedPreview } = require("./staged_preview.cjs");
const { updateActivationCommentWithCommit } = require("./update_activation_comment.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Check if we're in staged mode
@@ -22,7 +23,7 @@ async function main() {
try {
outputContent = fs.readFileSync(agentOutputFile, "utf8");
} catch (error) {
- core.setFailed(`Error reading agent output file: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error reading agent output file: ${getErrorMessage(error)}`);
return;
}
@@ -120,7 +121,7 @@ async function main() {
try {
validatedOutput = JSON.parse(outputContent);
} catch (error) {
- core.setFailed(`Error parsing agent output JSON: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Error parsing agent output JSON: ${getErrorMessage(error)}`);
return;
}
@@ -217,7 +218,7 @@ async function main() {
prTitle = pullRequest.title || "";
prLabels = pullRequest.labels.map(label => label.name);
} catch (error) {
- core.info(`Warning: Could not fetch PR ${pullNumber} details: ${error instanceof Error ? error.message : String(error)}`);
+ core.info(`Warning: Could not fetch PR ${pullNumber} details: ${getErrorMessage(error)}`);
// Exit with failure if we cannot determine the branch name
core.setFailed(`Failed to determine branch name for PR ${pullNumber}`);
return;
@@ -324,7 +325,7 @@ async function main() {
await exec.exec(`git push origin ${branchName}`);
core.info(`Changes committed and pushed to branch: ${branchName}`);
} catch (error) {
- core.error(`Failed to apply patch: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`Failed to apply patch: ${getErrorMessage(error)}`);
// Investigate why the patch failed by logging git status and the failed patch
try {
diff --git a/actions/setup/js/read_buffer.cjs b/actions/setup/js/read_buffer.cjs
index 4221c67735..1c70a28582 100644
--- a/actions/setup/js/read_buffer.cjs
+++ b/actions/setup/js/read_buffer.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* ReadBuffer Module
*
@@ -57,7 +59,7 @@ class ReadBuffer {
try {
return JSON.parse(line);
} catch (error) {
- throw new Error(`Parse error: ${error instanceof Error ? error.message : String(error)}`);
+ throw new Error(`Parse error: ${getErrorMessage(error)}`);
}
}
}
diff --git a/actions/setup/js/redact_secrets.cjs b/actions/setup/js/redact_secrets.cjs
index 103c3fb134..a42c8c31cc 100644
--- a/actions/setup/js/redact_secrets.cjs
+++ b/actions/setup/js/redact_secrets.cjs
@@ -35,7 +35,7 @@ function findFiles(dir, extensions) {
}
}
} catch (error) {
- core.warning(`Failed to scan directory ${dir}: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to scan directory ${dir}: ${getErrorMessage(error)}`);
}
return results;
}
@@ -90,7 +90,7 @@ function processFile(filePath, secretValues) {
}
return redactionCount;
} catch (error) {
- core.warning(`Failed to process file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to process file ${filePath}: ${getErrorMessage(error)}`);
return 0;
}
}
@@ -145,8 +145,10 @@ async function main() {
core.info("Secret redaction complete: no secrets found");
}
} catch (error) {
- core.setFailed(`Secret redaction failed: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Secret redaction failed: ${getErrorMessage(error)}`);
}
}
+const { getErrorMessage } = require("./error_helpers.cjs");
+
module.exports = { main };
diff --git a/actions/setup/js/render_template.cjs b/actions/setup/js/render_template.cjs
index 8cb35a9e21..b7a80c94dd 100644
--- a/actions/setup/js/render_template.cjs
+++ b/actions/setup/js/render_template.cjs
@@ -5,6 +5,8 @@
// Single-function Markdown → Markdown postprocessor for GitHub Actions.
// Processes only {{#if }} ... {{/if}} blocks after ${{ }} evaluation.
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
/**
@@ -79,7 +81,7 @@ function main() {
core.info("Template rendered successfully");
// core.summary.addHeading("Template Rendering", 3).addRaw("\n").addRaw("Processed conditional blocks in prompt\n").write();
} catch (error) {
- core.setFailed(error instanceof Error ? error.message : String(error));
+ core.setFailed(getErrorMessage(error));
}
}
diff --git a/actions/setup/js/resolve_mentions.cjs b/actions/setup/js/resolve_mentions.cjs
index caad8107f7..aabf44702b 100644
--- a/actions/setup/js/resolve_mentions.cjs
+++ b/actions/setup/js/resolve_mentions.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* @typedef {Object} MentionResolutionResult
* @property {string[]} allowedMentions - List of allowed mention usernames
@@ -19,6 +21,8 @@ function extractMentions(text) {
return [];
}
+ const { getErrorMessage } = require("./error_helpers.cjs");
+
const mentionRegex = /(^|[^\w`])@([A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?(?:\/[A-Za-z0-9._-]+)?)/g;
const mentions = [];
const seen = new Set();
@@ -73,7 +77,7 @@ async function getRecentCollaborators(owner, repo, github, core) {
return allowedMap;
} catch (error) {
- core.warning(`Failed to fetch recent collaborators: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to fetch recent collaborators: ${getErrorMessage(error)}`);
return new Map();
}
}
diff --git a/actions/setup/js/resolve_mentions_from_payload.cjs b/actions/setup/js/resolve_mentions_from_payload.cjs
index b8f7086e7f..63b4a13a81 100644
--- a/actions/setup/js/resolve_mentions_from_payload.cjs
+++ b/actions/setup/js/resolve_mentions_from_payload.cjs
@@ -6,6 +6,7 @@
*/
const { resolveMentionsLazily, isPayloadUserBot } = require("./resolve_mentions.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Resolve allowed mentions from the current GitHub event context
@@ -187,7 +188,7 @@ async function resolveAllowedMentionsFromPayload(context, github, core, mentions
return allowedMentions;
} catch (error) {
- core.warning(`Failed to resolve mentions for output collector: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to resolve mentions for output collector: ${getErrorMessage(error)}`);
// Return empty array on error
return [];
}
diff --git a/actions/setup/js/runtime_import.cjs b/actions/setup/js/runtime_import.cjs
index 690aee138c..453b72d057 100644
--- a/actions/setup/js/runtime_import.cjs
+++ b/actions/setup/js/runtime_import.cjs
@@ -5,6 +5,8 @@
// Processes {{#runtime-import filepath}} and {{#runtime-import? filepath}} macros
// at runtime to import markdown file contents dynamically.
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
const path = require("path");
@@ -138,7 +140,7 @@ function processRuntimeImports(content, workspaceDir) {
// Replace the macro with the imported content
processedContent = processedContent.replace(fullMatch, importedContent);
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
throw new Error(`Failed to process runtime import for ${filepath}: ${errorMessage}`);
}
}
diff --git a/actions/setup/js/safe_inputs_mcp_server.cjs b/actions/setup/js/safe_inputs_mcp_server.cjs
index 208fda0847..a6c9f97801 100644
--- a/actions/setup/js/safe_inputs_mcp_server.cjs
+++ b/actions/setup/js/safe_inputs_mcp_server.cjs
@@ -22,6 +22,7 @@ const { createServer, registerTool, start } = require("./mcp_server_core.cjs");
const { loadConfig } = require("./safe_inputs_config_loader.cjs");
const { createToolConfig } = require("./safe_inputs_tool_factory.cjs");
const { bootstrapSafeInputsServer, cleanupConfigFile } = require("./safe_inputs_bootstrap.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* @typedef {Object} SafeInputsToolConfig
@@ -100,7 +101,7 @@ if (require.main === module) {
try {
startSafeInputsServer(configPath, options);
} catch (error) {
- console.error(`Error starting safe-inputs server: ${error instanceof Error ? error.message : String(error)}`);
+ console.error(`Error starting safe-inputs server: ${getErrorMessage(error)}`);
process.exit(1);
}
}
diff --git a/actions/setup/js/safe_inputs_mcp_server_http.cjs b/actions/setup/js/safe_inputs_mcp_server_http.cjs
index 50a6b0fb78..36aacbe35e 100644
--- a/actions/setup/js/safe_inputs_mcp_server_http.cjs
+++ b/actions/setup/js/safe_inputs_mcp_server_http.cjs
@@ -25,6 +25,7 @@ const { validateRequiredFields } = require("./safe_inputs_validation.cjs");
const { generateEnhancedErrorMessage } = require("./mcp_enhanced_errors.cjs");
const { createLogger } = require("./mcp_logger.cjs");
const { bootstrapSafeInputsServer, cleanupConfigFile } = require("./safe_inputs_bootstrap.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Create and configure the MCP server with tools
@@ -341,7 +342,7 @@ if (require.main === module) {
}
startHttpServer(configPath, options).catch(error => {
- console.error(`Error starting HTTP server: ${error instanceof Error ? error.message : String(error)}`);
+ console.error(`Error starting HTTP server: ${getErrorMessage(error)}`);
process.exit(1);
});
}
diff --git a/actions/setup/js/safe_output_type_validator.cjs b/actions/setup/js/safe_output_type_validator.cjs
index 71d8ac7b96..550b4c8939 100644
--- a/actions/setup/js/safe_output_type_validator.cjs
+++ b/actions/setup/js/safe_output_type_validator.cjs
@@ -11,6 +11,7 @@
const { sanitizeContent } = require("./sanitize_content.cjs");
const { isTemporaryId } = require("./temporary_id.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Default max body length for GitHub content
@@ -73,7 +74,7 @@ function loadValidationConfig() {
cachedValidationConfig = parsed || {};
return cachedValidationConfig;
} catch (error) {
- const errorMsg = error instanceof Error ? error.message : String(error);
+ const errorMsg = getErrorMessage(error);
// Log as error since missing validation config is critical
if (typeof core !== "undefined") {
core.error(`CRITICAL: Failed to parse validation config: ${errorMsg}. Validation will be skipped.`);
diff --git a/actions/setup/js/safe_output_validator.cjs b/actions/setup/js/safe_output_validator.cjs
index 9ada5a5334..b279b5b0b2 100644
--- a/actions/setup/js/safe_output_validator.cjs
+++ b/actions/setup/js/safe_output_validator.cjs
@@ -3,6 +3,7 @@
const fs = require("fs");
const { sanitizeLabelContent } = require("./sanitize_label_content.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Load and parse the safe outputs configuration from config.json
@@ -18,7 +19,7 @@ function loadSafeOutputsConfig() {
const configContent = fs.readFileSync(configPath, "utf8");
return JSON.parse(configContent);
} catch (error) {
- core.warning(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to load config: ${getErrorMessage(error)}`);
return {};
}
}
diff --git a/actions/setup/js/safe_outputs_append.cjs b/actions/setup/js/safe_outputs_append.cjs
index 7561ac2995..88bb82dcd9 100644
--- a/actions/setup/js/safe_outputs_append.cjs
+++ b/actions/setup/js/safe_outputs_append.cjs
@@ -1,5 +1,7 @@
// @ts-check
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
/**
@@ -27,7 +29,7 @@ function createAppendFunction(outputFile) {
try {
fs.appendFileSync(outputFile, jsonLine);
} catch (error) {
- throw new Error(`Failed to write to output file: ${error instanceof Error ? error.message : String(error)}`);
+ throw new Error(`Failed to write to output file: ${getErrorMessage(error)}`);
}
};
}
diff --git a/actions/setup/js/safe_outputs_config.cjs b/actions/setup/js/safe_outputs_config.cjs
index debc341042..4f00984713 100644
--- a/actions/setup/js/safe_outputs_config.cjs
+++ b/actions/setup/js/safe_outputs_config.cjs
@@ -1,5 +1,7 @@
// @ts-check
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
const path = require("path");
@@ -30,7 +32,7 @@ function loadConfig(server) {
safeOutputsConfigRaw = {};
}
} catch (error) {
- server.debug(`Error reading config file: ${error instanceof Error ? error.message : String(error)}`);
+ server.debug(`Error reading config file: ${getErrorMessage(error)}`);
server.debug(`Falling back to empty configuration`);
safeOutputsConfigRaw = {};
}
diff --git a/actions/setup/js/safe_outputs_mcp_server.cjs b/actions/setup/js/safe_outputs_mcp_server.cjs
index 0abd29c73a..d2900d2722 100644
--- a/actions/setup/js/safe_outputs_mcp_server.cjs
+++ b/actions/setup/js/safe_outputs_mcp_server.cjs
@@ -17,6 +17,7 @@ const { createAppendFunction } = require("./safe_outputs_append.cjs");
const { createHandlers } = require("./safe_outputs_handlers.cjs");
const { attachHandlers, registerPredefinedTools, registerDynamicTools } = require("./safe_outputs_tools_loader.cjs");
const { bootstrapSafeOutputsServer, cleanupConfigFile } = require("./safe_outputs_bootstrap.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Start the safe-outputs MCP server
@@ -70,7 +71,7 @@ if (require.main === module) {
try {
startSafeOutputsServer();
} catch (error) {
- console.error(`Error starting safe-outputs server: ${error instanceof Error ? error.message : String(error)}`);
+ console.error(`Error starting safe-outputs server: ${getErrorMessage(error)}`);
process.exit(1);
}
}
diff --git a/actions/setup/js/safe_outputs_tools_loader.cjs b/actions/setup/js/safe_outputs_tools_loader.cjs
index 2e9edb80f2..aa12a1a5e4 100644
--- a/actions/setup/js/safe_outputs_tools_loader.cjs
+++ b/actions/setup/js/safe_outputs_tools_loader.cjs
@@ -1,5 +1,7 @@
// @ts-check
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const fs = require("fs");
/**
@@ -27,7 +29,7 @@ function loadTools(server) {
server.debug(`Successfully parsed ${tools.length} tools from file`);
return tools;
} catch (error) {
- server.debug(`Error reading tools file: ${error instanceof Error ? error.message : String(error)}`);
+ server.debug(`Error reading tools file: ${getErrorMessage(error)}`);
server.debug(`Falling back to empty tools array`);
return [];
}
diff --git a/actions/setup/js/substitute_placeholders.cjs b/actions/setup/js/substitute_placeholders.cjs
index 751b3a01ee..32c854ef70 100644
--- a/actions/setup/js/substitute_placeholders.cjs
+++ b/actions/setup/js/substitute_placeholders.cjs
@@ -1,24 +1,26 @@
-const fs = require("fs"),
- substitutePlaceholders = async ({ file, substitutions }) => {
- if (!file) throw new Error("file parameter is required");
- if (!substitutions || "object" != typeof substitutions) throw new Error("substitutions parameter must be an object");
- let content;
- try {
- content = fs.readFileSync(file, "utf8");
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
- throw new Error(`Failed to read file ${file}: ${errorMessage}`);
- }
- for (const [key, value] of Object.entries(substitutions)) {
- const placeholder = `__${key}__`;
- content = content.split(placeholder).join(value);
- }
- try {
- fs.writeFileSync(file, content, "utf8");
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
- throw new Error(`Failed to write file ${file}: ${errorMessage}`);
- }
- return `Successfully substituted ${Object.keys(substitutions).length} placeholder(s) in ${file}`;
- };
+const fs = require("fs");
+const { getErrorMessage } = require("./error_helpers.cjs");
+
+const substitutePlaceholders = async ({ file, substitutions }) => {
+ if (!file) throw new Error("file parameter is required");
+ if (!substitutions || "object" != typeof substitutions) throw new Error("substitutions parameter must be an object");
+ let content;
+ try {
+ content = fs.readFileSync(file, "utf8");
+ } catch (error) {
+ const errorMessage = getErrorMessage(error);
+ throw new Error(`Failed to read file ${file}: ${errorMessage}`);
+ }
+ for (const [key, value] of Object.entries(substitutions)) {
+ const placeholder = `__${key}__`;
+ content = content.split(placeholder).join(value);
+ }
+ try {
+ fs.writeFileSync(file, content, "utf8");
+ } catch (error) {
+ const errorMessage = getErrorMessage(error);
+ throw new Error(`Failed to write file ${file}: ${errorMessage}`);
+ }
+ return `Successfully substituted ${Object.keys(substitutions).length} placeholder(s) in ${file}`;
+};
module.exports = substitutePlaceholders;
diff --git a/actions/setup/js/temporary_id.cjs b/actions/setup/js/temporary_id.cjs
index 8e1e26fab1..9661d3f7ce 100644
--- a/actions/setup/js/temporary_id.cjs
+++ b/actions/setup/js/temporary_id.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
const crypto = require("crypto");
/**
@@ -116,7 +118,7 @@ function loadTemporaryIdMap() {
return result;
} catch (error) {
if (typeof core !== "undefined") {
- core.warning(`Failed to parse temporary ID map: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to parse temporary ID map: ${getErrorMessage(error)}`);
}
return new Map();
}
diff --git a/actions/setup/js/unlock-issue.cjs b/actions/setup/js/unlock-issue.cjs
index bfc2ee8cba..44924b48ea 100644
--- a/actions/setup/js/unlock-issue.cjs
+++ b/actions/setup/js/unlock-issue.cjs
@@ -7,6 +7,8 @@
* after agent workflow execution completes or fails
*/
+const { getErrorMessage } = require("./error_helpers.cjs");
+
async function main() {
// Log actor and event information for debugging
core.info(`Unlock-issue debug: actor=${context.actor}, eventName=${context.eventName}`);
@@ -55,7 +57,7 @@ async function main() {
core.info(`✅ Successfully unlocked issue #${issueNumber}`);
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
core.error(`Failed to unlock issue: ${errorMessage}`);
core.setFailed(`Failed to unlock issue #${issueNumber}: ${errorMessage}`);
}
diff --git a/actions/setup/js/update_activation_comment.cjs b/actions/setup/js/update_activation_comment.cjs
index b563bfb1c1..c73694e6a2 100644
--- a/actions/setup/js/update_activation_comment.cjs
+++ b/actions/setup/js/update_activation_comment.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
/**
* Update the activation comment with a link to the created pull request or issue
* @param {any} github - GitHub REST API instance
@@ -145,7 +147,7 @@ async function updateActivationCommentWithMessage(github, context, core, message
}
} catch (error) {
// Don't fail the workflow if we can't update the comment - just log a warning
- core.warning(`Failed to update activation comment: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to update activation comment: ${getErrorMessage(error)}`);
}
}
diff --git a/actions/setup/js/update_activation_comment.test.cjs b/actions/setup/js/update_activation_comment.test.cjs
index 0f5aa508d8..5eda58e8e3 100644
--- a/actions/setup/js/update_activation_comment.test.cjs
+++ b/actions/setup/js/update_activation_comment.test.cjs
@@ -5,7 +5,14 @@ const createTestableFunction = scriptContent => {
const beforeMainCall = scriptContent.match(/^([\s\S]*?)\s*module\.exports\s*=\s*{[\s\S]*?};?\s*$/);
if (!beforeMainCall) throw new Error("Could not extract script content before module.exports");
let scriptBody = beforeMainCall[1];
- return new Function(`\n const { github, core, context, process } = arguments[0];\n \n ${scriptBody}\n \n return { updateActivationComment };\n `);
+ // Mock the error_helpers module
+ const mockRequire = module => {
+ if (module === "./error_helpers.cjs") {
+ return { getErrorMessage: error => (error instanceof Error ? error.message : String(error)) };
+ }
+ throw new Error(`Module ${module} not mocked in test`);
+ };
+ return new Function(`\n const { github, core, context, process } = arguments[0];\n const require = ${mockRequire.toString()};\n \n ${scriptBody}\n \n return { updateActivationComment };\n `);
};
describe("update_activation_comment.cjs", () => {
let createFunctionFromScript, mockDependencies;
diff --git a/actions/setup/js/update_release.cjs b/actions/setup/js/update_release.cjs
index fbf939107d..a8a7623873 100644
--- a/actions/setup/js/update_release.cjs
+++ b/actions/setup/js/update_release.cjs
@@ -3,6 +3,7 @@
const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateStagedPreview } = require("./staged_preview.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
async function main() {
// Check if we're in staged mode
@@ -142,7 +143,7 @@ async function main() {
core.setOutput("release_tag", updatedRelease.tag_name);
}
} catch (error) {
- const errorMessage = error instanceof Error ? error.message : String(error);
+ const errorMessage = getErrorMessage(error);
const tagInfo = updateItem.tag || "inferred from context";
core.error(`Failed to update release with tag ${tagInfo}: ${errorMessage}`);
diff --git a/actions/setup/js/update_runner.cjs b/actions/setup/js/update_runner.cjs
index d283e5a979..109f20d53f 100644
--- a/actions/setup/js/update_runner.cjs
+++ b/actions/setup/js/update_runner.cjs
@@ -15,6 +15,7 @@
const { loadAgentOutput } = require("./load_agent_output.cjs");
const { generateStagedPreview } = require("./staged_preview.cjs");
const { removeDuplicateTitleFromDescription } = require("./remove_duplicate_title.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* @typedef {Object} UpdateRunnerConfig
@@ -276,7 +277,7 @@ async function runUpdateWorkflow(config) {
core.setOutput(outputUrlKey, updatedItem.html_url);
}
} catch (error) {
- core.error(`✗ Failed to update ${displayName} #${targetNumber}: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`✗ Failed to update ${displayName} #${targetNumber}: ${getErrorMessage(error)}`);
throw error;
}
}
diff --git a/actions/setup/js/upload_assets.cjs b/actions/setup/js/upload_assets.cjs
index 9eb258b935..cf9fc82a70 100644
--- a/actions/setup/js/upload_assets.cjs
+++ b/actions/setup/js/upload_assets.cjs
@@ -5,6 +5,7 @@ const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { getErrorMessage } = require("./error_helpers.cjs");
/**
* Normalizes a branch name to be a valid git branch name.
@@ -158,7 +159,7 @@ async function main() {
core.info(`Added asset: ${targetFileName} (${size} bytes)`);
} catch (error) {
- core.warning(`Failed to process asset ${asset.fileName}: ${error instanceof Error ? error.message : String(error)}`);
+ core.warning(`Failed to process asset ${asset.fileName}: ${getErrorMessage(error)}`);
}
}
@@ -184,7 +185,7 @@ async function main() {
core.info("No new assets to upload");
}
} catch (error) {
- core.setFailed(`Failed to upload assets: ${error instanceof Error ? error.message : String(error)}`);
+ core.setFailed(`Failed to upload assets: ${getErrorMessage(error)}`);
return;
}
diff --git a/actions/setup/js/validate_errors.cjs b/actions/setup/js/validate_errors.cjs
index 3d2e6fba01..d8abf90fe3 100644
--- a/actions/setup/js/validate_errors.cjs
+++ b/actions/setup/js/validate_errors.cjs
@@ -1,6 +1,8 @@
// @ts-check
///
+const { getErrorMessage } = require("./error_helpers.cjs");
+
function main() {
const fs = require("fs");
const path = require("path");
@@ -82,7 +84,7 @@ function main() {
}
} catch (error) {
console.debug(error);
- core.error(`Error validating log: ${error instanceof Error ? error.message : String(error)}`);
+ core.error(`Error validating log: ${getErrorMessage(error)}`);
}
}
diff --git a/actions/setup/setup.sh b/actions/setup/setup.sh
index 0718605ca2..4edd7104bb 100755
--- a/actions/setup/setup.sh
+++ b/actions/setup/setup.sh
@@ -111,6 +111,8 @@ SAFE_INPUTS_FILES=(
"read_buffer.cjs"
"generate_safe_inputs_config.cjs"
"setup_globals.cjs"
+ "error_helpers.cjs"
+ "mcp_enhanced_errors.cjs"
)
SAFE_INPUTS_COUNT=0
@@ -158,6 +160,8 @@ SAFE_OUTPUTS_FILES=(
"write_large_content_to_file.cjs"
"generate_compact_schema.cjs"
"setup_globals.cjs"
+ "error_helpers.cjs"
+ "mcp_enhanced_errors.cjs"
)
SAFE_OUTPUTS_COUNT=0